Insert images into the menu list - content-management-system

I'm trying to populate my menu items with an image/logo on each of the third menu list, please see example below.
I've been using Silverstripe to populate the menu items, below is my code so far without the images. Can someone please point me to the right direction on how I go about inserting the images/logos on the third level menu?
// initialise plugins
jQuery(function(){
jQuery('ul.sf-menu').superfish();
});
</script>
<ul class="sf-menu">
<% control Menu(1) %>
<li>
$MenuTitle
<% if Children %>
<ul><% control Children %>
<li>
$MenuTitle
<% if Children %>
<ul><% control Children %>
<li>
$MenuTitle
</li>
<% end_control %>
</ul><% end_if %>
</li>
<% end_control %>
</ul><% end_if %>
<!--<li>
menu item
</li>-->
</li> <!--current-->
<% end_control %><!-- <li>
menu item
</li> -->
</ul> <!--sf-menu-->
Thanks heaps.
S:)
UPDATE below is my Page.php, and I have insert $Image.SetSize(20,20) $MenuTitle to my third level menu. However everytime i tried to insert an image through CMS, there is error coming up in CMS. Sorry i'm new to this, any help would be appreciated.
<?php
class Page extends SiteTree {
public static $db = array(
);
public static $has_one = array(
'MenuImage' => 'Image'
);
function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab("Root.Content.Images", new ImageField('MenuImage','Menu image'));
return $fields;
}
}
class Page_Controller extends ContentController {
public static $allowed_actions = array (
);
public function init() {
parent::init();
// Note: you should use SS template require tags inside your templates
// instead of putting Requirements calls here. However these are
// included so that our older themes still work
Requirements::themedCSS('layout');
Requirements::themedCSS('typography');
Requirements::themedCSS('form');
}
}
here is the error info.
[User Error] Couldn't run query: SELECT * FROM "Page" WHERE "ID" = 15 Table 'ss_show.page' doesn't exist
POST /Show/admin/EditForm/field/MenuImage/EditFileForm
Line 525 in C:\wamp\www\Show\sapphire\core\model\MySQLDatabase.php

Assuming you have an image on your page object, you can render it in your template by doing something like this:
$MyImage.SetWidth(50) $MenuTitle
"$MyImage.SetWidth(50)" will output an image tag with an image resized to 50px wide. See the SilverStripe image reference for more info.

In case you don't have the menu image yet, follow the official documentation to do so: http://doc.silverstripe.org/sapphire/en/tutorials/2-extending-a-basic-site

I figured it out with soneone's help. Just in case others are in the same situation, it is because I didn't rebuild my database. Visit mysite.com/dev/build to rebuild the database. The code above in the update works after that. Thanks everyone! :)

Related

Create a subpart menu for a one page template in typo3

I integrate a one page parallax template in typo 3 in this i want to get a menu like below so i can access specific content on click , in a subpart of page object.
<ul class="nav navbar-nav navbar-right">
<li>HOME</li>
<li>ABOUT</li>
<li>PRICING</li>
<li>CONTACT</li>
<li>Call: +23-689-90 </li>
</ul>
Try
temp.contentnav = CONTENT
temp.contentnav {
table = tt_content
select {
pidInList = this
orderBy = sorting
where = colPos=0
languageField=sys_language_uid
}
renderObj = TEXT
renderObj {
field = header
wrap=|
typolink.parameter.field=pid
typolink.parameter.dataWrap=|#{field:uid}
if.isTrue.field=header
}
}
So you will get an menu of all items. Then again, you won't like that the menu item's title is taken from the header field. If your site is very small and you keep control over it, why don't you just hardcode this (look at the source, by default, each article has an id).
PS I copied that from http://www.typo3wizard.com/en/snippets/menus/content-element-navigation.html
EDIT on your getting started with TS question:
In your HTML Template:
<html>...
<!-- ###CONTENTNAV### START --><!-- ###CONTENTRIGHT### END -->
...</html>
In your TypoScript setup:
page.10.subparts {
# we fill the "subpart" (that's how this type of marker is called) with the temp object
CONTENTNAV < temp.contentnav
}
So the caret pointing left tells TYPO3 that in that region ("subpart"), it should add the content menu you've created with the TS snippet.
Note that you can also use "Marks" (###CONTENTNAV###, don't need start and end commentary, assign with page.10.marks) and the more modern fluid templates (<f:format.html>{contentnav}</f:format.html>), which are the future. You could start here: http://typo3buddy.com/typo3-template-tutorial/fluid/

TYPO3 tt_content: Add class to nav-wrap for specific menu element

I'm building a custom menu type and need to change the "outerOuterWrap" of this menu.
This is what i got:
tt_content.menu.20.102 < tt_content.menu.20.default
tt_content.menu.20.102 {
special = list
stdWrap {
outerWrap = <ul class="csc-menu csc-menu-102">|</ul>
}
1 = TMENU
1.NO {
(...)
}
}
And it will be rendered to:
<nav class="csc-default" id="c1416">
<ul class="csc-menu csc-menu-102">
(...)
</ul>
</nav>
How do I add a class to the nav tag without section_frame or layout? So that I get:
<nav class="csc-default custom-class" id="c1416">
Thank you!
I think this is in Line 454 of css_styled_content/static/setup.txt:
tt_content.stdWrap.innerWrap.cObject.default.20.20.10.value = csc-default
so you would need to set this value from inside your menu definition, just for your menu. Of which I'm not sure if it's possible.

TinyMCE - applying a style over bullets and multiple paragraphs applies the style to each bullet & para - how do I avoid?

I'm trying to use the theme_advanced_styles command within TinyMCE to add classes to selections of text within the TinyMCE editor. The problem is that if the paragraph contains bullets, then the style is applied throughout them (as well as to each individual paragraph).
What I want is just for the entire selection I made to have the style class added to the start of it. Ie if my style class is 'expandCollapse' I want:
<p class="expandCollapse">some content... some content... some content... some content... som content... some content... some content...
<ul>
<li>asdsadsadsadsasda</li>
<li>asdsadsa</li>
<li>sada</li>
</ul>
asome content... some content... some content... some content... some content... some content... some content... some content... </p>
But what I get is:
<p class="expandCollapse">some content... some content... some content... some content... some content... some content... some content...
<ul>
<li class="expandCollapse">asdsadsadsadsasda</li>
<li class="expandCollapse">asdsadsa</li>
<li class="expandCollapse">sada</li>
</ul>
</p>
<p class="expandCollapse">asome content... some content... some content... some content... some content... some content... some content... some content... </p>
Any ideas anyone?!
So I had to answer my own question as I needed an answer very quickly. It appears the behaviour I was experiencing is intentional? and certainly not something that has been removed in the very latest versions of TinyMCE (both 3.x and 4.x after testing).
With this in mind I ended up having to make a plugin to do what I wanted.
I borrowed a huge amount of code by Peter Wilson, from a post he made here: http://www.tinymce.com/forum/viewtopic.php?id=20319 So thanks very much for this Peter!
I ended up slightly changing the rules from my original question in that my solution adds an outer wrapping div around all the content I want to select. This method also allowed me to reliably then grab the required areas of html with jQuery in my front-end site.
My version of Peter's code is just very slightly modified from the original in order to add a class to the DIV, rename it, use a different button etc.
The plugin works perfectly and allows for a div to be created wrapping any amount of content within TinyMCE. The divs inserted have the class name I need also applied to it.
Add 'customDiv' to your plugin AND button bar for it to appear.
(function() {
tinymce.create("tinymce.plugins.Div", {
init : function(editor, url) {
editor.addCommand("mceWrapDiv", function() {
var ed = this, s = ed.selection, dom = ed.dom, sb, eb, n, div, bm, r, i;
// Get start/end block
sb = dom.getParent(s.getStart(), dom.isBlock);
eb = dom.getParent(s.getEnd(), dom.isBlock);
// If the document is empty then there can't be anything to wrap.
if (!sb && !eb) {
return;
}
// If empty paragraph node then do not use bookmark
if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))
bm = s.getBookmark();
// Move selected block elements into a new DIV - positioned before the first block
tinymce.each(s.getSelectedBlocks(s.getStart(), s.getEnd()), function(e) {
// If this is the first node then we need to create the DIV along with the following dummy paragraph.
if (!div) {
div = dom.create('div',{'class' : 'expandCollapse'});
e.parentNode.insertBefore(div, e);
// Insert an empty dummy paragraph to prevent people getting stuck in a nested block. The dummy has a '-'
// in it to prevent it being removed as an empty paragraph.
var dummy = dom.create('p');
e.parentNode.insertBefore(dummy, e);
//dummy.innerHTML = '-';
}
// Move this node to the new DIV
if (div!=null)
div.appendChild(dom.remove(e));
});
if (!bm) {
// Move caret inside empty block element
if (!tinymce.isIE) {
r = ed.getDoc().createRange();
r.setStart(sb, 0);
r.setEnd(sb, 0);
s.setRng(r);
} else {
s.select(sb);
s.collapse(1);
}
} else
s.moveToBookmark(bm);
});
editor.addButton("customDiv", {
//title: "<div>",
image: url + '/customdiv.gif',
cmd: "mceWrapDiv",
title : 'Wrap content in expand/collapse element'
});
}
});
tinymce.PluginManager.add("customDiv", tinymce.plugins.Div);
})();

Is passing parameters for controller overload from view good practice in .Net MVC

So right now I have a partial view that just has a list of possible actions, here is the main portion:
<%= Html.ActionLink("Show", "Show", new { id = dbId, css="/Content/Site.css" }) %> |
<%= Html.ActionLink("Edit", "Edit", new { id = dbId }) %> |
<%= Html.ActionLink("Delete", "Delete", new { id = dbId }, new { #class = "deleteLink" })%>|
<%= Html.ActionLink("Print", "Show", new { id = dbId, css="/Content/Other.css"}) %>
Essentially, there is a Show and and Print option, I decided it would be more convenient to not create a new view for print, and just overload the Show Action by passing an extra parameter that would tell which CSS to display, and then use ViewData to set the CSS for the view.
Is this good practice?
Should I create a new view? They are completely the same except for the CSS.
If the css is the only thing that is different, you could just include the css and set the media type to be picked up when the user prints from the browser, e.g.:
<style media="print" ...

Dojo events: getting it to work with dynamically added DOM elements

I have a method of a class as follows:
add_file: function(name, id, is_new){
// HTML: <div class="icon mime zip">name.zip <a>x</a></div>
var components = name.split('.');
var extension = components[components.length-1];
this.container.innerHTML += "<div id='"+id+"' class='icon mime "+extension+"'>"+name+" <a id='remove-"+id+"' href='#remove'>x</a></div>";
// Add event to a tag
dojo.connect(dojo.byId('remove-'+id), 'onclick', function(ev){
// here i am
});
},
All is working well, until I run this method more than once. The first time the event is registered correctly, and clicking the 'x' will run the "here i am" function. However, once I add more than one node (and yes, the ID is different), the event is registered to the last node, but removed from any previous ones.
In affect I have this:
<div id="field[photos]-filelist">
<div id="file1" class="icon mime jpg">file1.jpg <a id="remove-file1" href="#remove">x</a></div>
<div id="file2" class="icon mime jpg">file2.jpg <a id="remove-file2" href="#remove">x</a></div>
</div>
...and the remove link only works for the last node (remove-file2 in this case).
The problem is you are using the innerHTML +=
That is going to take the existing html, convert it to plain markup, and then completely create new nodes from the markup. In the process, all of the nodes with events get replaced with nodes that look exactly the same but are not connected to anything.
The correct way to do this is to use dojo.place(newNodeOrHTML, refNode, positionString)
var myNewHTML = "<div id='"+id+"' class='icon mime "+extension+"'>"+name+" <a id='remove-"+id+"' href='#remove'>x</a></div>"
//This won't work as is breaks all the connections between nodes and events
this.container.innerHTML += myNewHTML;
//This will work because it uses proper dom manipulation techniques
dojo.place(myNewHTML, this.container, 'last');