I have a MVC website and it had a searchbox with autocomplete, now I changed the layout using bootstrap. But now the autocomplete isn't been shown correctly anymore. See the picture the suggestions are not shown right.
the autocomplete goes through the text. I was fine before I used bootstrap.
I am using a SQL server to get the data and this is js file (I'm not good at ajax, i took it from a tutorial I followed)
$(function () {
var ajaxFormSubmit = function () {
var $form = $(this);
var options = {
url: $form.attr("action"),
type: $form.attr("method"),
data: $form.serialize()
};
$.ajax(options).done(function (data) {
var $target = $($form.attr("data-aptitude-target"));
var $newHtml = $(data);
$target.replaceWith($newHtml);
$newHtml.show("slide", 200);
});
return false;
};
var submitAutocompleteForm = function (event, ui) {
var $input = $(this);
$input.val(ui.item.label);
var $form = $input.parents("form:first");
$form.submit();
};
var createAutocomplete = function () {
var $input = $(this);
var options = {
source: $input.attr("data-aptitude-autocomplete"),
select: submitAutocompleteForm
};
$input.autocomplete(options);
};
$("form[data-aptituder-ajax='true']").submit(ajaxFormSubmit);
$("input[data-aptitude-autocomplete]").each(createAutocomplete);
});
this is the form in my view
<form method="get" action="#Url.Action("Index")"
data-aptitude-ajax="true" data-aptitude-target="#testList">
<input type="search" name="searchTerm" data-aptitude-autocomplete="#Url.Action("Autocomplete")" />
<input type="submit" value=Search />
And this is part of the controller of the view
public ActionResult Autocomplete(string term)
{
var model = db.tests
.Where(r => term == null || r.name.Contains(term))
.Select(r => new
{
label = r.name
});
return Json(model, JsonRequestBehavior.AllowGet);
}
//
// GET: /Test/
public ActionResult Index(string searchTerm = null)
{
var model = db.tests
.Where(r => searchTerm == null || r.name.StartsWith(searchTerm));
if (Request.IsAjaxRequest())
{
return PartialView("_Test", model);
}
return View(model);
}
I'm new to ajax as well as bootstrap 3.
I got the searchfunction and autocomplete from a tutorial I followed.
Anybody any idea on how to fix this, because it worked fine?
Thanks in advance!
I realise that this question in relatively old, however I'm not sure if you've found a solution and haven't got round to posting it??
Anyway - I have just run into this problem (using MVC 5, BootStrap 3 and typeahead.js 0.10.2).
I found this site, which kind of half solves "my/our" problem Typeahead CSS.
I've just ripped the following styles from the site and used them in my partial view (where the search box sits) and the box is now working and looks like all the demos on the typeahead.js example site
.tt-dropdown-menu {
min-width: 160px;
margin-top: 2px;
padding: 5px 0;
background-color: #fff;
border: 1px solid #ccc;
border: 1px solid rgba(0,0,0,.2);
*border-right-width: 2px;
*border-bottom-width: 2px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
-webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
-moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
box-shadow: 0 5px 10px rgba(0,0,0,.2);
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
}
.tt-suggestion {
display: block;
padding: 3px 20px;
}
.tt-suggestion.tt-is-under-cursor {
color: #fff;
background-color: #0081c2;
background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
background-image: -o-linear-gradient(top, #0088cc, #0077b3);
background-image: linear-gradient(to bottom, #0088cc, #0077b3);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
}
.tt-suggestion.tt-is-under-cursor a {
color: #fff;
}
.tt-suggestion p {
margin: 0;
}
the only problem that remains for me now is that the suggestion text (from typeahead) and the actual text in the input is not aligned and looks like you're viewing it after too many beers!
Related
I need to work with several sliders in the same page. Therefore I've created a class for the sliders (so there's only one jquery code) and I want to set the max and min values to attributes of the divs. They will then change according to the slider selected.
I'm guessing to do that I would need to use this at some point, or else it will target every class. Although I have no idea where to start or where to include it.
For now I've just applied the basic code, here it is:
HTML :
<div class="slider" slider-min="15" slider-max="250" svalue="132"></div><span class="slider-value"></span>
<div class="slider" slider-min="30" slider-max="300" svalue="165"></div><span class="slider-value"></span>
<div class="slider" slider-min="100" slider-max="500" svalue="300"></div><span class="slider-value"></span>
CSS :
.ui-slider { position: relative; text-align: left; background: #DADDD8; z-index: 0; }
.ui-slider { -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; }
.ui-slider .ui-slider-handle { background: #8FB339; position: absolute; z-index: 2; width: 15px; height: 15px; border-radius:5px; cursor:pointer; }
.ui-slider .ui-state-hover, .ui-slider .ui-state-active { background: #4B5842; }
.ui-slider .ui-slider-range { background: #C7D59F; position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
.ui-slider .ui-slider-range { -moz-box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; -webkit-box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; }
.ui-slider-horizontal { height: 5px; width:100px; margin:5px auto; }
.ui-slider-horizontal .ui-slider-handle { top: -5px; margin-left: -5px; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
.slider-value{
font-size:12px;
float:right;
margin-top:-16px;
margin-right:5px;
}
JS/JQUERY :
$( function() {
var div = $(".slider");
$( ".slider" ).slider({
range: "min",
slide: function( event, ui ) {
$( ".slider-value" ).html( ui.value );
},
min: div.data("slider-min"),
max: div.data("slider-max"),
value: div.data("svalue"),
})});
$( ".slider-value" ).html( $(this).slider('value') );
Here is this demo on jsfiddle
AND while I'm at it, I've got this other problem with the class/multiple sliders thing : when I want to display the current value of ONE slider, since it's a class it changes all the .slider-value spans. I do not know where to begin with this issue either.
Thank you for your time/help :)
Okay, you were on the right path, but you were throwing a few things in there that were redundant, probably from trying stuff and forgetting to remove them.
I've modified your code a little to make the function you have reusable. I've also nested the value field within the same div as the slider. This is to show you how easy jQuery makes it to find related elements, but you could relate them in other ways without having to nest them... Note that I didn't fix up the CSS, so it's a little messed up, but you can figure that out yourself...
The big change really though was the use of the id attribute, when using jQuery selectors, the 3 main types you can use (though there are others), are CSS class selectors $(".slider"), element selectors $("div"), and id selectors $("#slider1").
Just try the following changes to the HTML and JavaScript:
JavaScript / jQuery:
var func = function(div) {
var slide = $(div).slider({
range: "min",
slide: function( event, ui ) {
$(div).find(".slider-value").html( ui.value );
},
min: parseInt(div.attr("slider-min")),
max: parseInt(div.attr("slider-max")),
value: parseInt(div.attr("svalue")),
})
};
func($("#slider1"));
func($("#slider2"));
func($("#slider3"));
HTML:
<div class="slider" id="slider1" slider-min="15" slider-max="250" svalue="132"><span class="slider-value"></span>
</div>
<div class="slider" id="slider2" slider-min="30" slider-max="300" svalue="165"><span class="slider-value"></span></div>
<div class="slider" id="slider3" slider-min="100" slider-max="500" svalue="300"><span class="slider-value"></span></div>
I wrote some kind of that: http://jsfiddle.net/py3DE/203/ but when element is dragged into proper container, we can override it by dragging other div into its area. Could you tel me how i can block dragged elements, and if someone will try to override any element, div returns back into area with undragged divs?
if (!ui.draggable.closest('.empty').length) item = item.draggable()'
There is a simple way to do this. Basically, we'll remove the class empty and use the disable method.
Working Example: http://jsfiddle.net/Twisty/5rdxmp4p/
Minor CSS Change
.filled .item .closer {
display: block;
}
Drop Function
drop: function(ev, ui) {
if ($(this).hasClass("empty")) {
$(this).removeClass("empty").addClass("filled");
$(this).droppable("disable");
} else {
return false;
}
var item = ui.draggable;
if (!ui.draggable.closest('.empty').length) item = item.draggable(); // if item was dragged from the source list - clone it
this.innerHTML = ''; // clean the placeholder
item.css({
top: 0,
left: 0
}).appendTo(this); // append item to placeholder
}
Swapping the class allows the X button to appear. We then run the disable method to ensure that this specific item will no longer accept a dragged item. If the user drags an item to this spot, it is then reverted.
Update
Using Sortable: http://jsfiddle.net/Twisty/5rdxmp4p/2/
HTML
<div id="dragItems" class="source">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
</div>
<div id="sortItems" class="target">
</div>
CSS
body {
background: #fff;
}
.source,
.target {
margin: 20px;
min-height: 190px;
width: 400px;
border: 1px solid green;
}
.target {
border: 1px solid blue;
}
.item {
height: 20px;
margin: 5px;
padding: 5px;
border: 1px solid gray;
background-color: #cd8;
position: relative;
}
.closer {
float: right;
width: 20px;
height: 20px;
border: 0;
background-color: transparent;
}
.closer:hover {
background-color: transparent;
border: 0;
}
.empty {
height: 30px;
margin: 5px;
background: #eee;
border: 1px dashed #999;
}
.highlight {
border: 1px solid red;
background: #fff;
}
.highlight .item {
opacity: 0.3;
}
.ui-draggable-dragging {
z-index: 99;
opacity: 1 !important;
width: 378px;
}
jQuery
$(function() {
$("#sortItems").sortable({
axis: "y",
items: "> div",
placeholder: "empty",
dropOnEmpty: true,
stop: function(e, ui) {
var $it = ui.item;
if ($it.find(".closer").length == 0) {
var closeBtn = $("<span>", {
class: "closer"
});
$it.append(closeBtn);
closeBtn.button({
icon: "ui-icon-close",
label: "Close",
showLabel: false
}).click(function(ev) {
console.log("[INFO]: Closing ", $it);
$it.fadeTo(200, 0.0, function() {
$it.remove();
$("#sortItems").sortable("refresh");
});
});
}
}
});
$("#dragItems .item").draggable({
connectToSortable: "#sortItems",
revert: "invalid"
});
$("#sortItems").disableSelection();
});
Is there any knockout plugin for showing a nested context menu?
My specific need is to show a contextmenu for list items, that has a "SendTo" menuitem and the possible subItems have to be set at runtime.
In the apparent lack of suitable plugins I went for the more direct Knockout approach. I'm sure the code can be more elegantly packed in a custom binding but this is the solution I came up with, if anyone would need something similar. In my case the menu is build each time it's opened because it makes sense in my usecase. I'm sure the code can easily be customized to some other scenarios.
So... The markup:
<li data-bind="event: { contextmenu: $root.showSendToMenu }/>
is used to show the popup menu, for an item on a right click.
And the markup for the menu itself:
#*The send to popup menu*#
<ul class="context-menu" data-bind="visible:contextMenu.activeElement, style:{left:contextMenu.left, top:contextMenu.top}, template: { name: 'menu-item-template', foreach: contextMenu.items }, event: { mouseleave: contextMenu.contextMouseLeave }"></ul>
#*Template for a menu item*#
<script type="text/html" id="menu-item-template">
<li>
<!-- ko if: children -->
<span data-bind="text:text"></span>
<ul data-bind="template: { name: 'menu-item-template', foreach: children }"></ul>
<!-- /ko -->
<!-- ko if: !children -->
<!-- /ko -->
</li>
</script>
And in the viewModel, I have the following code (TypeScript):
contextMenu = { activeElement: ko.observable(null), left: ko.observable('0px'), top: ko.observable('200px'), items: ko.observableArray(<MenuItem[]>[]), contextMouseLeave : () => { this.contextMenu.activeElement(null); } };
showSendToMenu = (item, event) => {
//Set menu position
this.contextMenu.left(event.pageX + 'px');
this.contextMenu.top(event.pageY + 'px');
//Build the menu
var lines = [];
for (var i = 0; i < this.prodLines().length; i++) {
var line = this.prodLines()[i];
if (line.lists().length > 0) {
var lists = [];
for (var j = 0; j < line.lists().length; j++) {
var list = line.lists()[j];
lists.push(new MenuItem(list.name(), null, list));
}
lines.push(new MenuItem(line.name + "->", lists, line));
}
}
var items = [new MenuItem("SendTo ->", lines)];
//Set the menu
this.contextMenu.items(items);
this.contextMenu.activeElement(item);
}
onContextClick = (menuItem: MenuItem) => {
var sendToList = menuItem.tag;
var item = this.contextMenu.activeElement();
this.dropToList(item, sendToList);
//Hide the menu
this.contextMenu.activeElement(null);
}
And lastly, I used this piece of css to make the menu behave menu-like:
.context-menu {
position: absolute;
padding: 0;
margin: 0;
z-index: 1030;
background-color: #dddddd;
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.3);
min-width:100px;
border: 1px solid gray;
text-decoration:none;
}
.context-menu ul {
position: absolute;
z-index: 1031;
line-height: 1.6;
padding: 0;
margin: 0;
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.3);
display:none;
left:98px;
min-width:100px;
top:-1px;
background-color:#dddddd;
border: 1px solid gray;
text-decoration:none;
}
.context-menu li {
position:relative;
}
.context-menu li:hover > ul {
display:block;
}
.context-menu li {
padding: 4px 20px;
margin: 0;
list-style-type: none;
cursor: pointer;
white-space: nowrap;
color: #333333;
}
.context-menu ul > li:hover {
background-color: white;
text-decoration:underline;
}
I hope this will help someone
I created a jquery combobox which even when I open it using the button I want it to close when clicking on the page body. I'm using jQuery v1.10.1 and jQuery UI v1.10.3. When I originally wrote it I was using v111 and I had an onclick in the body to close it but when I upgraded the auto-complete never stayed open. I tried to make a jfiddle http://jsfiddle.net/abakoltuv/Lmbdn/ but the button doesn't work at all.
local css:
.textbox, input.combobox {
border: 1px solid #666666;
color: black;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10px;
}
span.combobox {
border-bottom: 1px solid #666666;
border-right: 1px solid #666666;
border-top: 1px solid #666666;
cursor: pointer;
display: inline-block;
font-size: 10px;
height: 8px;
padding: 2px 2px 4px;
position: relative;
top: 1px;
width: 10px;
}
<b>Brand</b><br />
<input type="text" onChange="setChangedFlag()" field="BRAND_ID" value="" id="BRAND_ID_display" name="BRAND_ID_display" size="22" class="combobox" style="width: 121px;"><span onClick="click_combobox_open('BRAND_ID_display')" class="combobox">▼</span>
<br /><input type="text" value="" id="BRAND_ID" name="BRAND_ID" style="background-color:#CCCCCC" class="textbox" size="22">
<script language="javascript" type="text/javascript">
<!--
$(document).ready(function() {
setup_combobox();
});
function setup_combobox()
{
var largest_size;
var data = [{"id":"1","value":"Able Planet"},{"id":"86","value":"Able Planet 123"},{"id":"2","value":"Acecad"},{"id":"3","value":"Action Life Media"},{"id":"4","value":"Adobe"},{"id":"5","value":"Bose"},{"id":"6","value":"Canon"},{"id":"7","value":"Delkin"}];
$("input.combobox").autocomplete({
html: 'html',
minLength: 0,
source: data ,
select: function(event, ui) {
if (ui.item) {
var width1 = $('#'+this.id).width();
$('#'+this.id).width((ui.item.value.length * 2/3) + 'em');
var width2 = $('#'+this.id).width();
if(width1 > width2)
$('#'+this.id).width(width1);
$('#'+this.id.substring(0, this.id.length - 8)).val(ui.item.id);
};
}
});
}
function click_combobox_open(display_ID)
{
var width1 = $('#'+display_ID).width();
$('#'+display_ID).width(($('#'+display_ID).val().length * 2/3) + 'em');
var width2 = $('#'+display_ID).width();
if(width1 > width2)
$('#'+display_ID).width(width1);
else
$('#'+display_ID).width(width2);
if(!$('#'+display_ID).autocomplete('widget').is(':visible'))
{
$('#'+display_ID).autocomplete('search','');
}
else
{
$('#'+display_ID).autocomplete('close');
}
}
//-->
</script>
Thanks
Aba
I finally figured it out I just needed to focus on the text box after opening it.
function click_combobox_open(display_ID)
{
var width1 = $('#'+display_ID).width();
$('#'+display_ID).width(($('#'+display_ID).val().length * 2/3) + 'em');
var width2 = $('#'+display_ID).width();
if(width1 > width2)
$('#'+display_ID).width(width1);
else
$('#'+display_ID).width(width2);
if(!$('#'+display_ID).autocomplete('widget').is(':visible'))
{
$('#'+display_ID).autocomplete('search','');
**$('#'+display_ID).focus();**
}
else
{
$('#'+display_ID).autocomplete('close');
}
}
I am trying to find a better way to assign classes to form elements in symfony. Currently, I can't seem to get away from assigning each one manually. ie:
$this->widgetSchema['title']->setAttribute("class","fieldInput");
$this->widgetSchema['tag_line']->setAttribute("class","fieldInput");
$this->widgetSchema['description']->setAttribute("class","fieldInput");
// etc
Things I tried without success
1) looping through $this->widgetSchema, treating it as an array and setting attributes to each key
2) $this->widgetSchema->setAttribute() but this only applied the class to the label that was generated, not the form element
There must be a way to hit all the fields without specifically directing them?
Can anyone point me in the right direction?
There is a way:
Create a sfWidgetFormSchemaFormatter in lib/widget, which contains for instance, this (code from symfonians):
class sfWidgetFormSchemaFormatterDiv extends sfWidgetFormSchemaFormatter
{
protected
$rowFormat = "<div class=\"form-row%is_error%\">\n %label%\n %error%\n %hel<div class='myfieldclass'%field%</div>\n p%\n%hidden_fields%</div>\n",
$errorRowFormat = "%errors%\n",
$helpFormat = '<div class="form-help">%help%</div>',
$decoratorFormat = "\n %content%";
public function formatRow($label, $field, $errors = array(), $help = '', $hiddenFields = null)
{
return strtr(parent::formatRow($label, $field, $errors, $help, $hiddenFields), array(
'%is_error%' => (count($errors) > 0) ? ' field_error' : '',
//'%is_required%' => $field,
));
}
}
Then, in your form, do:
$oDecorator = new sfWidgetFormSchemaFormatterDiv($this->getWidgetSchema());
$this->getWidgetSchema()->addFormFormatter('div', $oDecorator);
$this->getWidgetSchema()->setFormFormatterName('div');
Then you can style elements with the selector .myfieldclass input or whatever you want, this is a great way to change the structure/look of your forms.
From within the form class:
foreach ($this->getWidgetSchema()->getFields() as $field)
{
$field->setAttribute('class', 'custom-class');
}
You could also call that code from the constructor of a custom sfWidgetFormSchemaFormatter class if you have many form classes that need it:
public function __construct(sfWidgetFormSchema $widgetSchema)
{
parent::__construct($widgetSchema);
foreach ($this->getWidgetSchema()->getFields() as $field)
{
$field->setAttribute('class', 'custom-class');
}
}
I am having the same issue.
Situation
We have come to think that the separation between CSS and symfony's widget generation is a big learning curve for the integrators and we think there must be a way to leave the integrators more independent from the developers.
Client always want to have custom styled forms... and yet, custom handmade !DRY code is done. What I mean is that, Graphic designers do not design forms with only input text and label, they find all creative ways and our reality is to make it work in the framework to look the same as they design.
That's why we thought of using a sfWidgetFormSchemaFormatter, but form controllers are all different, and we wanted to be able to inject styling FROM the views... because it's an integration matter, not application matter. per se.
Solution path
My team-lead and I came up to a solution. Mostly using partials and looping through them. A form view could look like what follows.
Our solution is not perfect because we'd like to say by the call in the view which controller could get which class names. But it's better than to use CSS's input[type=text] because our client still uses < IE8. But at least,
So we thought of Why not mapping field id's with a className that could have a different behavior (different from label+input (and of course +helper+error if needs be)).
What we do is that we inject control style for those special controllers (e.g.: label+select+select+select+helper+error) let's say this Widget has id some_field_id and we need it to the parent <li>.
We could do it like this:
$node_classes_map => array('some_field_id'=>'date-selector')
So... now's time for some code:
First, we need to use the 'list' widgetFormatter:
<?php
// lib/form/SomeForm.php
class SomeForm extends BaseSomeForm
{
public function configure()
{
$this->widgetSchema->setFormFormatterName('list');
}
}
Or, you could use qais answer to have ALL forms as lists (at last!! I didn't knew before now).
The view:
<?php
// apps/appName/modules/moduleName/templates/someviewSuccess.php
$node_classes_map = array(
'some_field_id'=>'date-selector'
// .date-selector would have many select side by side.
// (no CSS for that in this example)
);
include_partial('global/patterns/formParent',
array(
'form'=>$form,
'form_classes'=>'labels-on-left',
'node_classes_map' => $node_classes_map
)
);
formParent looks like:
<?php
// apps/appName/templates/_patterns/formParent.php
$form_classes_attr = (isset($form_classes))?' class="'.$form_classes.'"':'';
$form_list_node_partial = 'global/patterns/listFormDefaultNode';
$model_name_lowercase = strtolower($form->getModelName());
$node_classes_map = (isset($node_classes_map))?$node_classes_map:array();
?>
<?php use_stylesheets_for_form($form) ?>
<?php use_javascripts_for_form($form); ?>
<form action="<?php
echo url_for($model_name_lowercase.'/'.($form->getObject()->isNew() ? 'create' : 'update').(!$form->getObject()->isNew() ? '?id='.$form->getObject()->getId() : ''))
?>"<?php echo $form_classes_attr;
?> method="post" <?php $form->isMultipart() and print 'enctype="multipart/form-data" '?>>
<h2><?php echo __(($form->getObject()->isNew()?'new.':'edit.').$model_name_lowercase.'.form.title'); ?></h2>
<fieldset>
<ol>
<?php
foreach($form as $item){
$node_classes = (isset($node_classes_map[$item->renderId()]))?$node_classes_map[$item->renderId()]:'';
include_partial($form_list_node_partial,
array(
'item'=>$item,
'node_classes' => $node_classes
)
);
}
?>
<ol>
</fieldset>
<?php echo $form->renderHiddenFields() ?>
<?php echo $form->renderGlobalErrors() ?>
<?php echo (!$form->getObject()->isNew())? '<input type="hidden" name="sf_method" value="put" />':''; ?>
</form>
Each form element gets rendered by either a custom one or listFormDefaultNode.
From there, you could come up with a different partial to render a controller differently from a mainstream label+input+helper+errors to something more complex like label+select+select+select+helper+erros.
This is my default form *Node
<?php
// apps/appName/templates/_patterns/listFormDefaultNode.php
/**
* Manual: http://www.symfony-project.org/forms/1_4/en/A-Widgets
*/
if(!$item->isHidden()){ ?>
<li class="<?php echo $item->renderId().((is_string($node_classes))?' '.$node_classes:''); ?>">
<?php echo $item->renderLabel(); ?>
<?php echo $item; ?>
<?php echo (!!$item->renderHelp())?'<span class="helpers">'.$item->renderHelp().'</span>':''; // I did not find any hasHelper(), so switching to bool ?>
<?php echo ($item->hasError())?'<span class="alertify error">'.$item->renderError().'</span>':''; ?>
</li>
<? }
Lastly, here is a start from my CSS:
Please note, here is a part of a project CSS and this uses part of concepts i'm developping with Snippies. Go there to get more ideas how I am structuring my CSS.
/* ****** Misc ****** */
/**
* General form views settings
**/
form ol, form ul {
list-style-type: none;
padding: 0;
margin: 0;
}
form input.text, form select {
display: block;
border: 0;
padding: 4px;
line-height: 12px;
font-size: 15px;
}
form select {
background-color: #e3e8eb;
color: #506775;
margin: 0;
}
form label {
color: #345569;
display: block;
font-weight: bold;
margin-bottom: 5px;
}
form input.text {
color: #345569;
border: none;
background-color: #e3e8eb;
color: #738996;
border: 0px solid #c3c987;
padding: 4px;
line-height: 12px;
width: 100%;
}
form fieldset {
padding: 0;
margin: 0;
border: none;
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #98a7af;
padding: 10px 0;
}
form li {
margin-bottom: 10px;
}
form li .helpers {
color: #98a7af;
}
/**
* /General form views settings
**/
/**
* General error messages
**/
.alertify {
padding: 0.8em;
margin-bottom: 1em;
border: 2px solid #ddd;
}
.alertify strong, .alertify p {
padding: 0 0 10px 0;
display: block;
}
.alertify ul {
margin: 0;
padding: 0 0 0 15px;
}
.alertify ul li {
padding: 0 0 5px 0;
}
.error, .alert {
background: #fbe3e4;
color: #8a1f11;
border-color: #fbc2c4;
}
/**
* /General error messages
**/
/* ****** /Misc ****** */
/* ****** Specialization ****** */
/**
* Form labels on the left
*/
form.labels-on-left fieldset {
padding: 0;
margin: 0;
padding-bottom: 10px;
margin-bottom: 10px;
}
form.labels-on-left li {
clear: both;
overflow: hidden;
}
form.labels-on-left li input.text, form.labels-on-left li select {
border: 0;
padding: 4px;
line-height: 12px;
}
form.labels-on-left li input.text {
width: 815px !important;
float: left;
padding: 6px;
color: #506775;
}
form.labels-on-left li select {
background-color: #e3e8eb;
color: #506775;
height: 26px;
width: 400px;
margin: 0;
float: left;
}
form.labels-on-left li .beside {
float: left;
}
form.labels-on-left li .beside a {
font-weight: bold;
padding: 5px 20px;
font-size: 14px;
display: block;
}
form.labels-on-left li label {
color: #345569;
width: 80px;
font-size: 120%;
text-align: right;
font-weight: bold;
float: left;
display: block;
padding: 5px 10px 0 0;
}
form.labels-on-left li .error span, form.labels-on-left li .helpers span {
padding: 5px;
display: block;
}
form.labels-on-left li .helpers {
width: 100%;
}
/**
* /Form labels on the left
*/
/* ****** /Specialization ****** */
This is old but for anyone trying to find this just go into the xxxxxFormFilter.php inside /lib/filter/doctrine/ and do this:
$this->getWidget('inputname')->setAttribute('class_name','class_name/id_name');
This way you can individually specify and control everything.
Depending on what base form you extend, you can add the following in the configure method:
public function configure()
{
foreach ($this->widgetSchema->getFields() as $field) {
$field->setAttribute('class','my-custom-class');
}
parent::configure();
}
I did mine in BaseFormDoctrine. You can use the same approach to add/override any attribute in the field or even add custom rules based on field type.
Apply the class to a parent element, not the individual elements:
TEMPLATE:
<form class="my-form" action="" method="">
// put widgets here
</form>
CSS:
.my-form select {}
.my-form input[type=text] {}
.my-form textarea {}
.my-form input[type=submit] {}
etc...