Is there a way when using Zend_Navigation to set a separator for pages?
For example, I call $this->navigation()->menu() in my view to render a navigation menu in a form of an unordered list. I would like there to be a separator between all menu items, for example |.
So, every menu item which is not last, would end with:
</a> | </li>
You can do it in CSS like this.
li:before {
content: "|";
}
li:first-child:before {
content: "";
}
li:first-child a {
margin-left: 0;
}
li a {
margin: 0 0 0 2mm;
}
The reverse logic here is for browser compatibility. IE < 9 doesn't support last-child but supports first-child.
Related
In my main menu, I need everything under a specific first level item to have a completely different layout.
In the past I have given a specific item a different wrap like this:
IFSUB = 1
IFSUB {
wrapItemAndSub.cObject = CASE
wrapItemAndSub.cObject {
key.field = uid
default = TEXT
default.value = <li>|</li>
1234 = TEXT
1234.value = <li class="mega">|</li>
}
}
But I need to do something different for level 2, 3, and 4 if they are children of uid 1234. Can I rewrite the above to say "if any pid = 1234 above this one then..."?
Wheres the problem then?
ul li a {
color: green;
}
ul li.mega li a {
color: blue; /* color for second level */
}
ul li.mega li li a {
color: pink; /* color for third level */
}
ul li.mega li li li a {
color: fuchsia; /* color for fourth level */
}
Is it possible to access an HTML attribute value in SASS?
I have a line of code that says
<ul id="my_id" data-count="3">
where the 3 is the result of some jQuery stuff. I need the 3 to calculate some CSS. How can I save it as a SASS variable?
Alternatively, is there a way of counting the number of child elements of a certain parent element? Say I have this code:
<ul id="my_id" data-count="3">
<li>First list item</li>
<li>Second list item</li>
<li>Third list item</li>
</ul>
(As you might have guessed, the value of data-count matches the number of list items.) Can SASS count the list items and save that number as a variable?
Any ideas would be greatly appreciated.
Sass is just a CSS generator. It doesn't really interact with your HTML, so you can't use HTML attributes as Sass variables.
However, CSS can select based on attributes. So it will be more long-winded than you might like, but you can do something like
ul[data-count="3"]:after
content: "There were three items in that list!"
And I think if you're willing to limit yourself only to a subset of very recent browsers†, you can use the CSS calc() function along with attr() to use the attribute in CSS-based calculations. But that's pretty bleeding edge.
†To be perfectly honest, I have no idea which versions of which browsers have fully implemented this. I'm pretty sure Firefox has it, though I've not used it, and I have no idea about other browsers. It is certainly not well-supported, at any rate.
It seems like you are trying to get the number of items inside your unordered list in CSS (maybe to change their size according to the number of siblings?).
Indeed, you cannot use a data-attribute as a Sass variable. However there is a pure CSS way to apply conditional styles given the number of items in the parent. Plus, it is very easily written in Sass.
Let's say your maximum number of items in your list is 10 and you want to compute the size of li tags based on the number of li tags there is in your list.
#for $i from 1 through 10 {
li:first-child:nth-last-child(#{$i}),
li:first-child:nth-last-child(#{$i}) ~ li {
width: (100%/$i);
}
}
This will output the following CSS:
li:first-child:nth-last-child(1),
li:first-child:nth-last-child(1) ~ li {
width: 100%;
}
li:first-child:nth-last-child(2),
li:first-child:nth-last-child(2) ~ li {
width: 50%;
}
li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
width: 33.33333%;
}
li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
width: 25%;
}
li:first-child:nth-last-child(5),
li:first-child:nth-last-child(5) ~ li {
width: 20%;
}
li:first-child:nth-last-child(6),
li:first-child:nth-last-child(6) ~ li {
width: 16.66667%;
}
li:first-child:nth-last-child(7),
li:first-child:nth-last-child(7) ~ li {
width: 14.28571%;
}
li:first-child:nth-last-child(8),
li:first-child:nth-last-child(8) ~ li {
width: 12.5%;
}
li:first-child:nth-last-child(9),
li:first-child:nth-last-child(9) ~ li {
width: 11.11111%;
}
li:first-child:nth-last-child(10),
li:first-child:nth-last-child(10) ~ li {
width: 10%;
}
Basically, this gives the li tags a width of:
100.0% when there is only one li tag
50.00% when there are 2 li tags
33.33% when there are 3 li tags
25.00% when there are 4 li tags
20.00% when there are 5 li tags
16.66% when there are 6 li tags
14.28% when there are 7 li tags
12.50% when there are 8 li tags
11.11% when there are 9 li tags
10.00% when there are 10 li tags
For a live example, please refer to this demo I did using the same trick. I hope it helps.
If you want to access an HTML attribute from CSS, you can use attr()
Check the doc
I know, there are at least 3 dozen questions like this on stackoverflow and still, I could not make this happen:
A simple table where thead is sticked/fixed at the top, and the tbody is scrolled.
I tried so much in the past days and now I ended up here crying for help.
A solution should work in IE8+ and newest FF, Chrome & Safari.
The difference to other "possible duplicates like this one is that I don't want to use two nested tables or jQuery (plain javascript is fine though).
Demo of what I want:
http://www.imaputz.com/cssStuff/bigFourVersion.html.
Problem is it doesn't work in IE, and I would be fine to use some JS.
Ok i got it:
You need to wrap the table in two DIVs:
<div class="outerDIV">
<div class="innerDIV">
<table></table>
</div>
</div>
The CSS for the DIVs is this:
.outerDIV {
position: relative;
padding-top: 20px; //height of your thead
}
.innerDIV {
overflow-y: auto;
height: 200px; //the actual scrolling container
}
The reason is, that you basically make the inner DIV scrollable, and pull the THEAD out of it by sticking it to the outer DIV.
Now stick the thead to the outerDIV by giving it
table thead {
display: block;
position: absolute;
top: 0;
left: 0;
}
The tbody needs to have display: block as well.
Now you'll notice that the scrolling works, but the widths are completely messep up. That's were Javascript comes in.
You can choose on your own how you want to assign it. I for myself gave the TH's in the table fixed widths and built a simple script which takes the width and assigns them to the first TD-row in the tbody.
Something like this should work:
function scrollingTableSetThWidth(tableId)
{
var table = document.getElementById(tableId);
ths = table.getElementsByTagName('th');
tds = table.getElementsByTagName('td');
if(ths.length > 0) {
for(i=0; i < ths.length; i++) {
tds[i].style.width = getCurrentComputedStyle(ths[i], 'width');
}
}
}
function getCurrentComputedStyle(element, attribute)
{
var attributeValue;
if (window.getComputedStyle)
{ // class A browsers
var styledeclaration = document.defaultView.getComputedStyle(element, null);
attributeValue = styledeclaration.getPropertyValue(attribute);
} else if (element.currentStyle) { // IE
attributeValue = element.currentStyle[vclToCamelCases(attribute)];
}
return attributeValue;
}
With jQuery of course this would be a lot easier but for now i was not allowed to use a third party library for this project.
Maybe we should change a method to archieve this goal.Such as:
<div><ul><li>1</li><li>2</li></ul></div> //make it fixed
<table>
<thead>
<tr><th>1</th><th>2</th></tr>
</thead>
<tfoot></tfoot>
<tbody></tbody>
</table>
Of course, this is not good to sematic.But it is the simplest way without js or jq.
Don't you think so?
I'm having problems with IE9 ignoring the select borders when printing a multiple select.
Here's how to recreate the problem:
Open IE9 on Windows 7.
Go to w3schools's multiple select edit page.
Now highlight the options and copy/paste until there is a long list of duplicates.
Then remove the size attribute.
Click on "Edit and Click Me" so that the page reloads and you now have your modified select in the second panel.
Now, print the document (even using the XPS viewer).
For me, all of the options are printed on the page, even though the select is only 4 option elements tall. This still happens to some degree if you leave the "size" attribute at the default value of 2, but it's far more obvious when it is changed or removed.
Is anyone else experiencing this? Is this an IE bug? Does anyone know of a workaround?
You can work around this by viewing the site in IE9's compatibility mode. Usually IE will determine that it cannot display a site properly and give you the option to turn on compatibility mode from within the address bar but sometimes you need to explicitly set it.
How to turn on compatibility mode - http://www.sevenforums.com/tutorials/1196-internet-explorer-compatibility-view-turn-off.html - I used the first one in method 2.
There doesn't seem to be any CSS solution for this. Instead, I wrote a small jQuery script that copies the <select multiple> contents into a <div>, so that it can be printed. Then I applied some CSS to make it look like a select, and only show the copy when actually printing.
Script:
//jQuery required
$(function() {
if(!$.browser.msie) return false;
$('select[multiple]').each(function() {
$lPrintableDiv = $('<div data-for="' + this.id + '" />').addClass($(this).attr('class')).addClass('printable');
//update printable on changes
$(this).after($lPrintableDiv).change(function($aEvent){
updatePrintable($aEvent.target);
});
//run once on load
updatePrintable(this);
});
});
function updatePrintable($aTarget) {
var $lSelect = $($aTarget);
var $lSelected = $($aTarget).val();
var $lPrintable = $('[data-for="'+$aTarget.id+'"]');
$($lPrintable).width($lSelect.width()).height($lSelect.height());
$($lPrintable).html('');
$($aTarget).children().each(function($lElm){
$lVal = $(this).val();
$lLabel = $('<label />').text($lVal);
$lOption = $('<input type="checkbox" />').val($lVal);
if($(this).is(':selected'))
$lOption.prop('checked', true);
$lPrintable.append($lOption).append($lLabel);
});
}
CSS:
.printable {
border: 1px solid grey;
display: none;
overflow: auto;
}
.printable label {
display: block;
font: .8em sans-serif;
overflow: hidden;
white-space: nowrap;
}
.printable [type="checkbox"] {
display: none;
}
.printable [type="checkbox"]:checked + label {
background: #3399ff;
color: white;
}
#media print {
select[multiple] { display: none; }
.printable { display: inline-block; }
.printable [type="checkbox"]:checked + label { background: grey; }
}
Also see the jsFiddle and original post about this fix
I have two connected sortable lists.
For the sake of my question, when I start dragging an item from #sortable1 to #sortable2, in the start event I want to cancel/ disable/ the drop in #sortable2
Nothing works?
$("#sortable1, #sortable2").sortable({
connectWith: "#sortable1, #sortable2",
start: startDrag
});
function startDrag(event, ui) {
$("#sortable2").css("opacity","0.5");
// $("#sortable2").sortable("cancel"); // goes whooooo
/* docs say:
If the sortable item is being moved from one connected sortable to another:
$(ui.sender).sortable('cancel');
will cancel the change. Useful in the 'receive' callback.
*/
// $("#sortable1").sortable("cancel"); // I only want to cancel dropping in sortable2...
// $("#sortable2").sortable("disable"); // disables only after the drop event
// $("#sortable2").sortable("destroy"); // same as "disable"
}
function stopDrag(event, ui) {
$("#sortable2").css("opacity","1.0");
// $("#sortable2").sortable("enable");
}
My JSFiddle here: http://jsfiddle.net/tunafish/m32XW/
I have found 2 more questions like mine:
jQuery sortable('disable') from start event not entirely working like expected
http://forum.jquery.com/topic/disable-a-sortable-while-dragging-with-connectedlists
No responses..
Anything appreciated!
EDIT: I also tried to overlay a div like a modal on the sortable, but can still be dragged to that way. The only thing that worked is a show/hide, but that's not an option for me.
OK here is my app; two lists of images, sortable and you can copy over from the connected list.
If an item already exists in the target it's disabled.
Hopefully useful to someone...
JSFiffle here: http://jsfiddle.net/tunafish/VBG5V/
CSS:
.page { width: 410px; padding: 20px; margin: 0 auto; background: darkgray; }
.album { list-style: none; overflow: hidden;
width: 410px; margin: 0; padding: 0; padding-top: 5px;
background: gray;
}
.listing { margin-bottom: 10px; }
.album li { float: left; outline: none;
width: 120px; height: 80px; margin: 0 0 5px 5px; padding: 5px;
background: #222222;
}
li.placeholder { background: lightgray; }
JS:
$("ul, li").disableSelection();
$(".album, .favorites").sortable({
connectWith: ".album, .favorites",
placeholder: "placeholder",
forcePlaceholderSize: true,
revert: 300,
helper: "clone",
stop: uiStop,
receive: uiReceive,
over: uiOver
});
$(".album li").mousedown(mStart);
var iSender, iTarget, iIndex, iId, iSrc, iCopy;
var overCount = 0;
/* everything starts here */
function mStart() {
// remove any remaining .copy classes
$(iSender + " li").removeClass("copy");
// set vars
if ($(this).parent().hasClass("listing")) { iSender = ".listing"; iTarget = ".favorites"; }
else { iSender = ".favorites"; iTarget = ".listing"; }
iIndex = $(this).index();
iId = $(this).attr("id");
iSrc = $(this).find("img").attr("src");
iCopy = $(iTarget + " li img[src*='" + iSrc + "']").length > 0; // boolean, true if there is allready a copy in the target list
// disable target if item is allready in there
if (iCopy) { $(iTarget).css("opacity","0.5").sortable("disable"); }
}
/* when sorting has stopped */
function uiStop(event, ui) {
// enable target
$(iTarget).css("opacity","1.0").sortable("enable");
// reset item vars
iSender = iTarget = iIndex = iId = iSrc = iCopy = undefined;
overCount = 0;
// reinit mousedown, live() did not work to disable
$(".album li").mousedown(mStart);
}
/* rolling over the receiver - over, out, over etc. */
function uiOver(event, ui) {
// only if item in not allready in the target
if (!iCopy) {
// counter for over/out (numbers even/uneven)
overCount++;
// if even [over], clone to original index in sender, show and fadein (sortables hides it)
if (overCount%2) {
if (iIndex == 0) { ui.item.clone().addClass("copy").attr("id", iId).prependTo(iSender).fadeIn("slow"); }
else { ui.item.clone().addClass("copy").attr("id", iId).insertAfter(iSender + " li:eq(" + iIndex + ")").fadeIn("slow"); }
}
// else uneven [out], remove copies
else { $(iSender + " li.copy").remove(); }
}
// else whoooooo
}
/* list transfers, fix ID's here */
function uiReceive(event, ui) {
(iTarget == ".favorites") ? liPrefix = "fli-" : liPrefix = "lli-";
// set ID with index for each matched element
$(iTarget + " li").each(function(index) {
$(this).attr("id", liPrefix + (index + 1)); // id's start from 1
});
}
HTML:
<div class="page">
<div class="container">
<h2>Photo Album</h2>
<ul class="listing album">
<li id="li-1"><img src="tn/001.jpg" /></li>
<li id="li-2"><img src="tn/002.jpg" /></li>
<li id="li-3"><img src="tn/003.jpg" /></li>
<li id="li-4"><img src="tn/004.jpg" /></li>
<li id="li-5"><img src="tn/005.jpg" /></li>
</ul>
</div>
<div style="clear:both;"></div>
<div class="container">
<h2>Favorites</h2>
<ul class="favorites album">
<li id="fli-1"><img src="tn/001.jpg" /></li>
<li id="fli-2"><img src="tn/002.jpg" /></li>
<li id="fli-3"><img src="tn/010.jpg" /></li>
</ul>
</div>
</div>
/* docs say:
If the sortable item is being moved from one connected sortable to another:
$(ui.sender).sortable('cancel');
will cancel the change. Useful in the 'receive' callback.
*/
This code was what I spent 30 minutes looking for!
Ok I found some sort of hack for this.
When an item is moved from #sortable1 to #sortable2, when dragged over #sortable2 there is a list item added with class .placeholder
So in UI's over event I did
$("#sortable2 li.placeholder").hide();
Than set it back with UI's stop event
$("#sortable2 li.placeholder").show();
This is only for visuals though.. The item is still moved into #sortable2 so you need to remove() it there. To mimic copying you need to add a clone() back in #sortable2. You can get it's original index() in UI's start event and than use insertAfter(id - 1)
At the moment I can only clone in UI's receive event, I would prefer in UI's over but can't get it to work..