How to create a HMENU/TMENU with Icons that came from a Mask field (text)? - mask

With the extension "Mask" I've added some fields in Page Templates to assign Icons to pages. Also you can use a checkbox to activate the selected icon in menus. Menu meaning this case: I've also made a Content Element with Mask where you only enter a UID and all subpages of that UID will be created as <li> list.
I've set up the following fields in Page Templates:
page_01_icon (String): will contain something like "icon-home"
page_02_color (String): this will be the color of the icon or the background-color for the list element; depends on `page_color_background`, valid values are any css hex colors like "#a5011c"
page_02_color_text (String): if set, the text color will be changed to this
page_03_menu (Checkbox): checked == `page_icon` will be shown; else only the title of the page
page_04_icon_only_menu (Checkbox): checked == only icon will be shown, title not (not needed for my question, I use this only in the main menu)
page_05_color_background (Checkbox): if checked `page_color` is used as background color for this list element, if not the icon will get the colored with `page_color`; if `page_color` is not set at all neither icon or the background will get an color
I am very new to Typo3, but I actually get the above code work with the normal header menu on my page. It was a hard way there but that part works. For the header menu I could do it in FLUID, but this is now a lib and I need to do the same here but with TypoScript - no matter what I try I coudn't get it right. Most examples and how-tos rely on "if uid = 1..25" do something else. But I need multiple if elses for this. I think how I've done in FLUID is the right way, now trying to get the same logic to TypoScript... and ended up here.
Page Template Fields in Mask
This is how I added the fields in Mask
Content-Fields
Pages -> Edit -> Content-Fields (of Mask-Fields)
Main Menu Bar
This is what I've done with FLUID (the main menu bar). Icon-only + Icon and Title + Title only.
Spoken in simple PHP logic I would do the following (just to explain the main thinking / way I try in TypoScript):
// dont need to check if page_01_icon is set: field is required
// dont need to check if page_03_menu is checked: icons in this typo3 lib will always be displayed
// just assume that $title holds the title and $url the url to that page
foreach(....) {
// save html/css code in var for text color if a color is set
if(isset($page_02_color_text)) {
$textColorHTML = ' style="color' . $page_02_color_text . '"';
} else {
$textColorHTML = '';
}
// save html/css code in background of <li> if background-checkbox is checked and a color is set
if ($page_05_color_background == 1 && isset(page_02_color)) {
$liBackgroundHTML = ' style="background-color:' . $page_05_color_background . '"';
} else {
$liBackgroundHTML = '';
}
echo '<li' . $liBackgroundHTML . '></i> ' . $title . </li>';
}
Basicly thats what I tryied to try in TypoScript :)
What I "have":
A Mask template-file with the following content:
<f:cObject typoscriptObjectPath="lib.linkListAuto" data="{data}" />
The lib.linkListAuto-file:
This is the default version without the php logic from above. here I need to "translate" the php logic into.. I couldn't even post a half way woring script cuz everything I#ve tried ended as the wrong way :/
lib.linkListAuto = COA
lib.linkListAuto {
1 = HMENU
1 {
special = directory
special.value.field = tx_mask_link_root_id
wrap = <ul class="list-group">|</ul>
stdWrap.if.isTrue.data = register:count_menuItems
1 = TMENU
1 {
NO = 1
NO {
allWrap = <li class="list-group-item">|</li>
stdWrap.htmlSpecialChars = 1
ATagTitle.field = description // subtitle // title
}
}
}
}
How can I say in TypoScript "render this way every link (sub-page) that comes",
but if a color ist set and the checkbox for use_color_as_background ist checked: change the rendering for this entry and give the <li> a background-color
also change the text color if it is set
and finaly add the icon in front of the page-title
?
Please help with ideas that dont come up with "if uid equals X"-examples. Had enough of them, they work, yes, but I cant change them to what I am trying to do.

You need to understand the concept of TypoScript.
So the name may be misleading. TypoScript is not a scripting language but a configuration language. So you can't use the concept of a sequential computation.
In this way you configure your rendering.
Anyway you can add some logic to the rendering in the form of the .stdWrap.if function which can control whether a value is printed in the output.
The other important functionality is string concatenation: in TypoScript you can use COAs (Content Object Array) to build up a string where you decide for each array element how it is displayed.
For building up the string <li' . $liBackgroundHTML . '></i> ' . $title . </li> you might use something like:
temp.li_tag = COA
temp.li_tag {
10 = TEXT
10.value = <li
// if ($page_05_color_background == 1 && isset(page_02_color)) {
// $liBackgroundHTML = ' style="background-color:' . $page_05_color_background . '"';
// } else {
// $liBackgroundHTML = '';
// }
20 = TEXT
20.field = page_05_color_background
20.noTrimWrap = | style="background-color:|"|
20.if.isTrue.field = page_02_color
30 = TEXT
30.value = ><a href="
40 = TEXT
40.field = title
40.dataWrap = <i class="{field.page_01_icon}"></i> |
40.stdWrap.typolink {
parameter.field = uid
// if(isset($page_02_color_text)) {
// $textColorHTML = ' style="color' . $page_02_color_text . '"';
// } else {
// $textColorHTML = '';
// }
ATagParams.cObject = TEXT
ATagParams.cObject {
field = page_02_color_text
wrap = style="color|"
if.isTrue.field = page_02_color_text
}
}
50 = TEXT
50.value = </li>
}

Related

Positioning icons

Since I'm complete new to this, I'll try to be as clear as possible.
My questions concerns the positioning of my buttonicons for my mobile pages.
Basically, for every page there is an option to select an icon which gets displayed to the left of the page title.
How would I change the positioning below in order to get the icons displayed on the right side of the page titles. Unfortunately I can't post a screenshot of the current and ideal situation. Ideally I would like to have the page titles slightly more to the left.
I hope this still makes sense without a screenshot.
if($page->buttonicon){
$icon = "<img src=\"icons/".$page->buttonicon."\" style=\"position:relative; top:33px\">";
}
else{
$icon = "<img src=\"images/noicon.png\" style=\"position:relative; top:33px\">";
}
$menurow = "<li id=row_".$page->id." style=\"display:$rstyle\">$icon<a class=\"".$bs."\" href=\"".trim($page->url)."\" $target >".$page->title."</a></li>\n";
If I may say, referring me to another post doesn't help me a lot since I'm completely new to this, so in order to avoid getting confused - I need this particular code to be used/rewritten.. :)
Any help is more than welcome, thanks in advance!!
EDIT
The CSS stylesheet doesn't seem to affect the positioning. The CSS stylesheet only seems to be called for the layout of the navigation buttons. The icons within the navigation buttons are related to the first code mentioned above.
With CSS you can float HTML elements example:
float:left
float:right
If that doesnt work try setting the position of the element to absolute and physically margining the element into place:
position:absolute;
margin: 10px, 10px, 10px, 10px
In your code, this inserts the image:
if($page->buttonicon){
$icon = "buttonicon."\" style=\"position:relative; top:33px\">";
}
else{
$icon = "";
}
and this inserts the title:
$menurow = "id." style=\"display:$rstyle\">$iconurl)."\" $target >".$page->title."\n";
If no CSS interferes, you should be able to simply switch the order of those two statements to get the desired effect.
EDIT
Thanks. Something like the code below? I tried (without any luck):
if($page->buttonicon){
$menurow = "<li id=row_".$page->id." style=\"display:$rstyle\">$icon<a class=\"".$bs."\" href=\"".trim($page->url)."\" $target >".$page->title."</a></li>\n";
$icon = "<img src=\"icons/".$page->buttonicon."\" style=\"position:relative; top:33px\">";
}
else{
$icon = "<img src=\"images/noicon.png\" style=\"position:relative; top:33px\">";
}

CSS expanding div with variable height

I found this code for collapsible css div here at stackoverflow and I want to use multiple instances of this on one page, but when I click any of the "read more" links it opens the first instance only.
How to modify this script to make each link open only the div associated with it?.
The source: http://jsfiddle.net/QkKej/
function growDiv() {
var growDiv = document.getElementById('grow');
if (growDiv.clientHeight) {
growDiv.style.height = 0;
} else {
var wrapper = document.querySelector('.measuringWrapper');
growDiv.style.height = wrapper.clientHeight + "px";
}
document.getElementById("more-button").value=document.getElementById("morebutton").value=='Read more'?'Read less':'Read more';
}
The page where i'm using it: http://www.udayansalimbanerjee.com/articles
Modify these attributes:
id="more-button" ---> class="more-button"
id="grow" ---> class="grow"
Additionally complete onclick:
onclick="growDiv(this)"
Then you can use jQuery (I see, the site supports it):
function growDiv(elem) {
var elEq = $(".more-button").index(elem);
$(elem).val(
$(".grow").eq(elEq).is(":visible") ? "Read more" : "Read less"
);
$(".grow").eq(elEq).slideToggle("fast");
}
This should do the trick. :)
Edit: I almost forget the "Read more/less" button.

adding tooltip to datagrid headers in dojo

I have a dojo datagrid which is poulated dynamically. I want to add tooltip to table headers of this datagrid. How can i do that?My datagrid simply has the structure of table and table headers. the fields get populated dynamically.
Thanks,
Sreenivas
Easiest Way
The easiest way, (Without overriding the template) would be to add a domNode to your layout header definition. So for example, when you are setting the "name" for your column in the layout, you can have something like ...
var layout = [
{
cells: [
{
name:"<i id="sometooltip" class='icon-large icon-edit'></i> Col",
field: "_item",
formatter: lang.hitch( this, this.formatter )
}
]
}];
What you then want to do is in your formatter, you want to check to see if "sometooltip" has be initialized as a tooltip, and do your connect.. You can use any tooltip.. not just dijit.Tooltip.
There are a few words of caution though. Because the formatter will run every time there is a redraw on your grid, you might want to think up better ways of creating your tooltip. For instance, you might want to add it to onGridRowHeaderHover, or you might want to just use CSS3 and use [title] attribute to create a CSS3 header.
Also. You can't just create the tooltip once, because the header is constantly rebuilt every redraw/change of data.
The Correct Way
The correct way would be to override the Grid template for the header, and include your tooltip in there. You would then extend the header equivalent of onStyleRow (which I can't remember), but basically the method that places the headers, and create your tooltip then.
I would definitely use the second option by overriding the template. Because otherwise you will find the grid glitchy.
For a pre-AMD Dojo version this is the monkey patch that we included in our globally scoped javascript resource. My other answer was after we switched to an AMD Dojo version.
// HeaderBuilder.generateHtml
// If showTooltips is true, the header contents will be used as the tooltip text.
var old_HeaderBuilder_generateHtml = dojox.grid._HeaderBuilder.prototype.generateHtml;
dojox.grid._HeaderBuilder.prototype.generateHtml = function(inGetValue, inValue){
var html = this.getTableArray(), cells = this.view.structure.cells;
dojox.grid.util.fire(this.view, "onBeforeRow", [-1, cells]);
for(var j=0, row; (row=cells[j]); j++){
if(row.hidden){
continue;
}
html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGridInvisible">');
for(var i=0, cell, markup; (cell=row[i]); i++){
cell.customClasses = [];
cell.customStyles = [];
if(this.view.simpleStructure){
if(cell.headerClasses){
if(cell.headerClasses.indexOf('dojoDndItem') == -1){
cell.headerClasses += ' dojoDndItem';
}
}else{
cell.headerClasses = 'dojoDndItem';
}
if(cell.attrs){
if(cell.attrs.indexOf("dndType='gridColumn_") == -1){
cell.attrs += " dndType='gridColumn_" + this.grid.id + "'";
}
}else{
cell.attrs = "dndType='gridColumn_" + this.grid.id + "'";
}
}
markup = this.generateCellMarkup(cell, cell.headerStyles, cell.headerClasses, true);
// content
markup[5] = (inValue != undefined ? inValue : inGetValue(cell));
// set the tooltip for this header to the same name as the header itself
try {
markup[5] = markup[5].replace("class","title='"+cell.name+"' class");
} catch(e) {
console.debug(e);
}
// styles
markup[3] = cell.customStyles.join(';');
// classes
markup[1] = cell.customClasses.join(' '); //(cell.customClasses ? ' ' + cell.customClasses : '');
html.push(markup.join(''));
}
html.push('</tr>');
}
html.push('</table>');
return html.join('');
};
I had a similar requirement. I wanted each DataGrid column header to use the name given to the column as the tooltip since our DataGrids weren't always showing the full column name due to the columns' widths sometimes being squeezed. I added a monkey patch (below) that is done with an AMD Dojo version:
require(
[
"dojo/dom",
"dojox/grid/DataGrid",
"dijit/_Widget",
"dijit/form/FilteringSelect",
"dijit/form/MultiSelect",
"dijit/layout/ContentPane",
"dijit/layout/TabContainer",
"dojox/grid/_Grid",
"dijit/MenuItem",
"dijit/MenuSeparator",
"dojox/grid/_Builder",
"dojox/grid/cells/_base",
"dojox/grid/util",
"dojo/parser",
"dojo/_base/array",
"dojo/_base/lang",
"dojo/ready",
"dojo/query",
"dijit/registry",
],
function(dom, dojox_grid_DataGrid, dijit__Widget, dijit_form_FilteringSelect,
dijit_form_MultiSelect, dijit_layout_ContentPane, dijit_layout_TabContainer,
dojox_grid__Grid, MenuItem, MenuSeparator, dojox_grid__Builder,
dojox_grid_cells__Base, dojox_grid_util,
parser, array, dojoLang, ready, dojoQuery, registry) {
var old_HeaderBuilder_generateHtml = dojox_grid__Builder._HeaderBuilder.prototype.generateHtml;
dojox_grid__Builder._HeaderBuilder.prototype.generateHtml = function(inGetValue, inValue){
var html = this.getTableArray(), cells = this.view.structure.cells;
dojox_grid_util.fire(this.view, "onBeforeRow", [-1, cells]);
for(var j=0, row; (row=cells[j]); j++){
if(row.hidden){
continue;
}
html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGridInvisible">');
for(var i=0, cell, markup; (cell=row[i]); i++){
cell.customClasses = [];
cell.customStyles = [];
if(this.view.simpleStructure){
if(cell.headerClasses){
if(cell.headerClasses.indexOf('dojoDndItem') == -1){
cell.headerClasses += ' dojoDndItem';
}
}else{
cell.headerClasses = 'dojoDndItem';
}
if(cell.attrs){
if(cell.attrs.indexOf("dndType='gridColumn_") == -1){
cell.attrs += " dndType='gridColumn_" + this.grid.id + "'";
}
}else{
cell.attrs = "dndType='gridColumn_" + this.grid.id + "'";
}
}
markup = this.generateCellMarkup(cell, cell.headerStyles, cell.headerClasses, true);
// content
markup[5] = (inValue != undefined ? inValue : inGetValue(cell));
// set the tooltip for this header to the same name as the header itself
markup[5] = markup[5].replace("class","title='"+cell.name+"' class");
// styles
markup[3] = cell.customStyles.join(';');
// classes
markup[1] = cell.customClasses.join(' '); //(cell.customClasses ? ' ' + cell.customClasses : '');
html.push(markup.join(''));
}
html.push('</tr>');
}
html.push('</table>');
return html.join('');
};
}
);
Note that if there's any chance that any markup may be added to the cell.name then you'll need to add a condition that will somehow extract just the text from it to be the tooltip, or somehow generate a tooltip that won't throw a rendering error, or avoid setting a tooltip altogether for that column.

cObject in Typolink assigned with border-content

Basically, I (think I ) need to know how to assign borderContent to a cObject, when it is a typolink parameter.
To tell the whole story: I'm using perfect lightbox, and I want it to open the lightbox when a text is clicked, and display the images that are in a single content element in the border section.
Looking through the manual, i found this code:
page.20 = TEXT
page.20.value = Open an image in a lightbox
page.20.typolink {
title = This is my caption
parameter.cObject = IMG_RESOURCE
parameter.cObject = fileadmin/image2.jpg
parameter.cObject.file.maxW = 600
parameter.cObject.file.maxH = 600
ATagParams = rel="lightbox[mySet]"
}
which is working fine. But I don't want the path to be hard set, but the content to be loaded from the border section, as I said. But if I try the following:
page.20 = TEXT
page.20.value = Open an image in a lightbox
page.20.typolink {
title = This is my caption
parameter.cObject = IMG_RESOURCE
parameter.cObject < styles.content.getBorder
parameter.cObject.file.maxW = 600
parameter.cObject.file.maxH = 600
ATagParams = rel="lightbox[mySet]"
}
the link is gone.
So I GUESS I'm assigning the content wrong. Somebody knows the answer?
Thanks!
(If of any help, I use automaketemplate..)
Assigning styles.content.getBorder will just assign the full content elements from the border column. This will not get you anywhere.
You will need to manually load the content elements from the border column, of course this can be done with TypoScript. It should be something like this:
page.20 = TEXT
page.20 {
value = Open an image in a lightbox
typolink {
ATagParams = rel="lightbox[mySet]"
title = This will be the title attribute
parameter.cObject = CONTENT
parameter.cObject {
table = tt_content
select {
pidInList = this
where = colPos = 3
}
renderObj = IMG_RESOURCE
renderObj.file {
import = uploads/pics
import.field = image
import.listNum = 0
width = 600
height = 600
}
}
}
}
Basically this will load all content elements on the border position from the current page. Render the first image in the list of images and return you the resource.

How to hide jQuery Sub-Menus(ddsmoothmenu)?

I'm new to jQuery and i must admit that i've understood nothing yet, the syntax appears to me as an unknown language although i thought that i had my experiences with javascript.
Nevertheless i managed it to implement this menu in my asp.net masterpage's header.
Even got it to work that the content-page is loaded with ajax with help from here.
But finally i'm failing with the menu to disappear when the new page was loaded asynchronously. I dont know how to hide this accursed jQuery Menu.
Following the part of the js-file where the events are registered for hiding/disappearing. I dont know how to get the part that is responsible for it and even i dont know how to implement that part in my Anchor-onclick function where i dont have a reference to the jQuery Object.
buildmenu:function($, setting){
var smoothmenu=ddsmoothmenu
var $mainmenu=$("#"+setting.mainmenuid+">ul") //reference main menu UL
$mainmenu.parent().get(0).className=setting.classname || "ddsmoothmenu"
var $headers=$mainmenu.find("ul").parent()
$headers.hover(
function(e){
$(this).children('a:eq(0)').addClass('selected')
},
function(e){
$(this).children('a:eq(0)').removeClass('selected')
}
)
$headers.each(function(i){ //loop through each LI header
var $curobj=$(this).css({zIndex: 100-i}) //reference current LI header
var $subul=$(this).find('ul:eq(0)').css({display:'block'})
$subul.data('timers', {})
this._dimensions={w:this.offsetWidth, h:this.offsetHeight, subulw:$subul.outerWidth(), subulh:$subul.outerHeight()}
this.istopheader=$curobj.parents("ul").length==1? true : false //is top level header?
$subul.css({top:this.istopheader && setting.orientation!='v'? this._dimensions.h+"px" : 0})
$curobj.children("a:eq(0)").css(this.istopheader? {paddingRight: smoothmenu.arrowimages.down[2]} : {}).append( //add arrow images
'<img src="'+ (this.istopheader && setting.orientation!='v'? smoothmenu.arrowimages.down[1] : smoothmenu.arrowimages.right[1])
+'" class="' + (this.istopheader && setting.orientation!='v'? smoothmenu.arrowimages.down[0] : smoothmenu.arrowimages.right[0])
+ '" style="border:0;" />'
)
if (smoothmenu.shadow.enable){
this._shadowoffset={x:(this.istopheader?$subul.offset().left+smoothmenu.shadow.offsetx : this._dimensions.w), y:(this.istopheader? $subul.offset().top+smoothmenu.shadow.offsety : $curobj.position().top)} //store this shadow's offsets
if (this.istopheader)
$parentshadow=$(document.body)
else{
var $parentLi=$curobj.parents("li:eq(0)")
$parentshadow=$parentLi.get(0).$shadow
}
this.$shadow=$('<div class="ddshadow'+(this.istopheader? ' toplevelshadow' : '')+'"></div>').prependTo($parentshadow).css({left:this._shadowoffset.x+'px', top:this._shadowoffset.y+'px'}) //insert shadow DIV and set it to parent node for the next shadow div
}
$curobj.hover(
function(e){
var $targetul=$subul //reference UL to reveal
var header=$curobj.get(0) //reference header LI as DOM object
clearTimeout($targetul.data('timers').hidetimer)
$targetul.data('timers').showtimer=setTimeout(function(){
header._offsets={left:$curobj.offset().left, top:$curobj.offset().top}
var menuleft=header.istopheader && setting.orientation!='v'? 0 : header._dimensions.w
menuleft=(header._offsets.left+menuleft+header._dimensions.subulw>$(window).width())? (header.istopheader && setting.orientation!='v'? -header._dimensions.subulw+header._dimensions.w : -header._dimensions.w) : menuleft //calculate this sub menu's offsets from its parent
if ($targetul.queue().length<=1){ //if 1 or less queued animations
$targetul.css({left:menuleft+"px", width:header._dimensions.subulw+'px'}).animate({height:'show',opacity:'show'}, ddsmoothmenu.transition.overtime)
if (smoothmenu.shadow.enable){
var shadowleft=header.istopheader? $targetul.offset().left+ddsmoothmenu.shadow.offsetx : menuleft
var shadowtop=header.istopheader?$targetul.offset().top+smoothmenu.shadow.offsety : header._shadowoffset.y
if (!header.istopheader && ddsmoothmenu.detectwebkit){ //in WebKit browsers, restore shadow's opacity to full
header.$shadow.css({opacity:1})
}
header.$shadow.css({overflow:'', width:header._dimensions.subulw+'px', left:shadowleft+'px', top:shadowtop+'px'}).animate({height:header._dimensions.subulh+'px'}, ddsmoothmenu.transition.overtime)
}
}
}, ddsmoothmenu.showhidedelay.showdelay)
},
function(e){
var $targetul=$subul
var header=$curobj.get(0)
clearTimeout($targetul.data('timers').showtimer)
$targetul.data('timers').hidetimer=setTimeout(function(){
$targetul.animate({height:'hide', opacity:'hide'}, ddsmoothmenu.transition.outtime)
if (smoothmenu.shadow.enable){
if (ddsmoothmenu.detectwebkit){ //in WebKit browsers, set first child shadow's opacity to 0, as "overflow:hidden" doesn't work in them
header.$shadow.children('div:eq(0)').css({opacity:0})
}
header.$shadow.css({overflow:'hidden'}).animate({height:0}, ddsmoothmenu.transition.outtime)
}
}, ddsmoothmenu.showhidedelay.hidedelay)
}
) //end hover
}) //end $headers.each()
$mainmenu.find("ul").css({display:'none', visibility:'visible'})
}
one link of my menu what i want to hide when the content is redirected to another page(i need "closeMenu-function"):
<li>Delivery Control</li>
In short: I want to fade out the submenus the same way they do automatically onblur, so that only the headermenu stays visible but i dont know how.
Thanks, Tim
EDIT: thanks to Starx' private-lesson in jQuery for beginners i solved it:
I forgot the # in $("#smoothmenu1"). After that it was not difficult to find and call the hover-function from the menu's headers to let them fade out smoothly:
$("#smoothmenu1").find("ul").hover();
Regards,
Tim
Ok, I didn't read your whole post. But if you are using a jQuery Menu, that menu should having a container element like <div> or <ul> and they will either have a class or id
In case it is a id then do
$(document).ready(function() {
$("#myelementid").hide();
});
In case it has a class then do
$(document).ready(function() {
$(".myelementclass").hide();
});
Hope this helps
UPDATE
$("#mainmenu").children().hide(); // to hide all child elements
or
$(".submenu").hide(); //to hide every submenu

Resources