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
Related
How can I make a loop inside currentSlide(1) so I want everytime .each work to add currentSlide(1) then currentSlide(2) then currentSlide(3) and so on.
<div class="approach" id="app">
<style>
#media (max-width: 600px){
.btn {
padding: 2px 2px 2px 2px !important; */
}}
#myBtnContainer{
display: flex;
}
/* Create three equal columns that floats next to each other */
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 282px;
}
.column:hover{
border: 1px solid #777;
}
/* Clear floats after rows */
.row:after {
content: "";
display: table;
clear: both;
}
/* Content */
.content {
width: 100%;
height: 400px;
overflow: hidden;
/*display: flex;*/
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
}
.content img{
object-fit: cover;
height: auto;
width: 100%;
position: absolute;
}
/* The "show" class is added to the filtered elements */
.show {
display: block;
}
/* Style the buttons */
.btn {
border: none;
outline: none;
padding: 10px 10px;
background-color: #333333;
cursor: pointer;
color: white;
}
.btn:hover {
background-color: #ddd;
}
.btn.active {
background-color: #666;
color: white;
}
.modal {
display: none;
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: black;
}
/* Modal Content */
.modal-content {
position: relative;
background-color: #fefefe;
margin: auto;
padding: 0;
width: 90%;
max-width: 500px;
}
/* The Close Button */
.close {
color: white !important;
position: absolute;
top: 170px;
right: 25px;
font-size: 35px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #999;
text-decoration: none;
cursor: pointer;
}
.mySlides {
display: none;
}
.cursor {
cursor: pointer
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -50px;
color: white;
font-weight: bold;
font-size: 20px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
}
/* Position the "next button" to the right */
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
/* On hover, add a black background color with a little bit see-through */
.prev:hover,
.next:hover {
background-color: rgba(0, 0, 0, 0.8);
}
/* Number text (1/3 etc) */
.numbertext {
color: #f2f2f2;
font-size: 12px;
padding: 8px 12px;
position: absolute;
top: 0;
}
img {
margin-bottom: -4px;
}
.caption-container {
text-align: center;
background-color: black;
padding: 2px 16px;
color: white;
}
.demo {
opacity: 0.6;
}
.active,
.demo:hover {
opacity: 1;
}
img.hover-shadow {
transition: 0.3s
}
.hover-shadow:hover {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)
}
.mySlides img{
padding-top: 70px;
background-color: black;
}
div.desc {
padding: 15px;
text-align: center;
}
#media (max-width:600px) {
.close {
color: white !important;
position: absolute;
top: 120px;
right: 25px;
font-size: 45px;
font-weight: bold;
z-index: 1000;
}
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 83px;
}
}
#media (max-width: 320px){
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 70px;
}
}
#media only screen and (min-width: 812px) {
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 90px;
} }
</style>
<body>
<!-- MAIN (Center website) -->
<div class="container">
<h1>GALLERY</h1>
<div id="myBtnContainer">
<button class="btn" onclick="filterSelection('conversion')"> Conversion</button>
<button class="btn" onclick="filterSelection('fixed-hybrid')"> Fixed Hybrid</button>
<button class="btn" onclick="filterSelection('removal-bar-over-denture')"> Removable Bar Over Denture</button>
<button class="btn" onclick="filterSelection('surgical-guides')"> Surgical Guides</button>
<button class="btn active" onclick="filterSelection('all')"> Show all</button>
</div>
<br>
<!-- Portfolio Gallery Grid -->
<div class="row">
<% #galleries.each do |g| %>
<% [g.image1, g.image2, g.image3, g.image4, g.image5].compact.each_with_index do |image, index| %>
<div class="column <%= g.product_name %>">
<div class="content">
<%= image_tag image.url, style: "width:100%", onclick: "openModal();currentSlide(#{index + 1})" ,class: "hover-shadow cursor"%>
</div>
</div>
<% end %>
<% end %>
<!-- END GRID -->
</div>
<!-- END MAIN -->
</div>
<div id="myModal" class="modal">
<span class="close cursor" onclick="closeModal()">×</span>
<div class="modal-content">
<% #galleries.each do |g| %>
<% [g.image1, g.image2, g.image3, g.image4, g.image5].compact.each_with_index do |image, index| %>
<div class="mySlides">
<div class="numbertext">1 / 4</div>
<%= image_tag image.url, style: "width:100%" %>
</div>
<% end %>
<% end %>
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
<div class="caption-container">
<p id="caption">hr</p>
</div>
</div>
<script>
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("column");
if (c == "all") c = "";
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
}
}
function w3AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {element.className += " " + arr2[i];}
}
}
function w3RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
// Add active class to the current button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function(){
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
</script>
</div>
<script>
function openModal() {
document.getElementById('myModal').style.display = "block";
}
function closeModal() {
document.getElementById('myModal').style.display = "none";
}
var slideIndex = 1;
showSlides(slideIndex);
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("demo");
var captionText = document.getElementById("caption");
if (n > slides.length) {slideIndex = 1}
if (n < 1) {slideIndex = slides.length}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " active";
captionText.innerHTML = dots[slideIndex-1].alt;
}
</script>
Looks like you just need an index to interpolate into currentSlide.
Start by removing duplication and instead of checking every related image with <% if g.image1.present? %> put them into an array and iterate over it with:
<% [g.image1, g.image2, g.image3].compact.each_with_index do |image, index|
compact will make sure that only present images are there, so you don't have to use if present any more.
And then use onclick: "openModal();currentSlide(#{index + 1})" (as index starts at 0, and you seem to need it to start from 1)
Update:
<% #galleries.each do |g| %>
<% [g.image1, g.image2, g.image3, g.image4, g.image5].compact.each_with_index do |image, index| %>
<div class="column <%= g.product_name %>">
<div class="content">
<%= image_tag image.url,
alt: "conversion",
style: "width:100%",
onclick: "openModal();currentSlide(#{index + 1})",
class: "hover-shadow cursor" %>
</div>
</div>
I have a model that called LinksListWidgetModel that contains an IEnumerable property named Links that contains a list of my website links.
In my Razor view, I have two columns (i.e. one for the grid "col-md-8" and one for another tool "col-md-4". I have a foreach loop that adds each link to the grid tool. I am trying to achieve the following look: Matrix View, however the buttons don't wrap after three, it just continues throughout the width of the page. I am using Bootstrap4.x and flexbox.
I tried following the example in this question: How I can make nice looking matrix of buttons with bootstrap 3?, but that didn't fix the issue either.
Here is my code:
LinksListGrid.cshtml:
#if (Model == null)
{
#Html.Partial("_WidgetNotConfigured") }
else
{
<div class="btn-group btn-matrix" role="group">
#foreach (var link in Model.Links)
{
<div class="linkContainer-gridItem">
<button>
<a class="linkContainer-gridItem-link btn btn-default" href="#link.Url">
#if (!string.IsNullOrEmpty(link.Icon))
{
<div>
<i class="icon #link.Icon"></i>
</div>
}
#link.Label
</a>
</button>
</div>
}
</div>
}
LinkContainer.scss:
.linkContainer {
padding: 1rem;
margin-bottom: 2rem;
position: relative;
background: #fff;
border-radius: 8px;
border: 1px solid #dddfe2;
.linkContainer-title {
color: #fff;
background: $colorBrandDarkBlue;
padding: 1rem;
border-radius: 5px;
margin: -.5rem -.5rem 1rem -.5rem;
font-weight: 400;
}
.linkContainer-list {
list-style: none;
padding: 0;
margin-bottom: 0;
font-family: "Montserrat",sans-serif;
.linkContainer-item {
position: relative;
.linkContainer-link {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
padding: .75rem .5rem;
color: $colorBrandBlue;
font-weight: 400;
font-size: 18px;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
text-decoration: none;
background-color: transparent;
font-family: "Montserrat",sans-serif;
}
.icon:before {
font-size: 30px;
margin-right: 1rem;
}
}
.linkContainer-item:after {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
border-top: 1px dotted;
opacity: .25;
}
}
.linkContainer-grid {
width: 290px;
display: block;
margin: 0 auto;
padding: 0;
padding-bottom: 19px;
font-family: "Montserrat",sans-serif;
text-align: center;
.linkContainer-gridItem {
background-color: $colorBrandBlue;
border-radius: 25px;
width: 120px;
height: 120px;
margin: 10px;
display: inline-block;
vertical-align: top;
.linkContainer-gridItem-link {
color: white;
text-decoration: none;
display: flex;
flex-direction: column;
justify-content: center;
height: 100%;
padding: 20px 10px;
}
.icon {
font-size: 30px;
margin-bottom: 0.25rem;
}
}
}
#media screen and (max-width: 767px) {
&.linkContainer-gridLayout {
padding: 0;
}
}
}
.btn-matrix {
> .btn {
&:nth-child(3n+4) {
clear: left;
margin-left: 0;
}
&:nth-child(n+4) {
margin-top: -1px;
}
&:first-child {
border-bottom-left-radius: 0;
}
&:nth-child(3) {
border-top-right-radius: 4px !important;
}
&:nth-last-child(3) {
border-bottom-left-radius: 4px !important;
}
&:last-child {
border-top-right-radius: 0;
}
}
}
It ends up looking like this: Grid View
How can I change this to make it look like the first screenshot's matrix/grid display? After every 3 buttons it goes on the second line.
I don't think clear:left; will work on flexbox. But there are other ways to do it.
HTML & SCSS way
I think you would be better off just styling .btn-matrix yourself, without mixing .btn-group styles, because Bootstrap .btn-group brings in lots of noice on its .btn children, such as border-radius, border, etc. You would need to style them using your own styles anyway so why bother.
I think the following structure should be generic enough you can use to construct a matrix:
<div class="btn-matrix btn-matrix-white" role="group">
<a class="btn" href="#">
<div class="fa-stack fa-2x">
<i class="fas fa-circle fa-stack-2x" />
<i class="fas fa-chart-bar fa-stack-1x" />
</div>
Reports
</a>
...
</div>
First of all, in your original HTML structure, you had a button that wraps an anchor link. That's not necessary because Bootstrap has classes to style an anchor link to just look like a button.
Secondly, I am using icon stacking method to construct icons with circle backgrounds. You can read about it here: https://fontawesome.com/how-to-use/on-the-web/styling/stacking-icons
Finally, here is the styles:
$numOfMatrixItemPerRow: 3;
$matrixItemBorderWidth: 1px;
.btn-matrix {
display: flex;
flex-flow: row wrap;
box-shadow: 0 0 1rem #ccc;
border: 1px solid transparent;
border-radius: .25rem;
> .btn {
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: flex-start;
flex-grow: 0;
flex-shrink: 0;
padding: 5%;
width: calc(100% / #{$numOfMatrixItemPerRow});
border-radius: 0;
}
&.btn-matrix-white {
> .btn {
background-color: #fff;
border-right: $matrixItemBorderWidth solid #ddd;
border-bottom: $matrixItemBorderWidth solid #ddd;
.fa-stack-2x {
color: var(--primary);
}
.fa-stack-1x {
color: #fff;
}
&:nth-child(#{$numOfMatrixItemPerRow}n) {
border-right: none !important;
}
&:last-child {
border-bottom: none !important;
}
}
}
}
Really nothing tricky there except you would need to use SASS Interpolation to involve $numOfMatrixItemPerRow variable into calculations:
Display .btn-matrix as a wrappable flex row
Set the width of each button to be 100% / $numOfMatrixItemPerRow so that each row will contain the exact number of items before breaking into new rows
Display .btn as flexbox column so that you can easily align the icons and text there
Set the right and bottom border of each button, with exceptions of the last one on each row and last one
demo: https://jsfiddle.net/davidliang2008/1wqost69/201/
ASP.NET MVC way
Now since you're using ASP.NET MVC, I think there is another approach you can consider. That is, in the loop where you loop though each link from the model, you can define a variable there and do something like:
<div class="btn-matrix">
#for (int i = 0; i < Model.Links.Count(); i++)
{
var link = Model.Links[i];
if (i % numOfItemsPerRow == 0)
{
<div class="row">
}
<div class="col-md-4">
<a class="btn" href="#link.Url">
#if (!string.IsNullOrEmpty(link.Icon))
{
<div>
<i class="icon #link.Icon"></i>
</div>
}
#link.Label
</a>
</div>
if ((i+1) % numOfItemsPerRow == 0 || i + 1 == Model.Links.Count())
{
</div>
}
}
</div>
I'm just making things up but hopefully you see where I am going.
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();
});
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!
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');
}
}