Jquery UI Autocomplete- How to format results AND add button at end? - jquery-ui

I've figured out how to change the formatting on my results:
https://github.com/salmanarshad2000/demos/blob/v1.0.4/jquery-ui-autocomplete/custom-html-in-dropdown.html
And I've figured out how I can add a link to the bottom of the results:
Jquery Auto complete append link at the bottom
What I can't figure out is how to do both at the same time.
The closest that I've come is the following:
$( "#search1" ).autocomplete({
source: products,
minLength: 3,
select: function( event, ui ) {
event.preventDefault();
},
focus: function(event, ui) {
event.preventDefault();
}
}).data("ui-autocomplete")._renderItem = function(ul, item) {
console.log(ul.content)
var $div = $("<div></div>");
$("<img style='height:76px;'>").attr("src", item.image).appendTo($div);
$("<span></span>").text(item.label).appendTo($div);
($div).append( "<a href='https://google.com'>Click Me</a>" )
return $("<li></li>").append($div).appendTo(ul);
};
The problem is that adds the link to each individual returned result, rather than slamming it onto the end of the list.
I've tried various incarnations of wrapping the link (li, div, etc) but nothing's working.
What do I need to do to get a link as the last thing on the list?
JS Fiddle: http://jsfiddle.net/spgbq6w7/13/

Consider the following code.
Working Example: http://jsfiddle.net/Twisty/wur8vok9/23/
HTML
Search: <input id="search1">
JavaScript
var products = [{
value: "MS-Word",
label: "Microsoft Word 2013",
image: "https://upload.wikimedia.org/wikipedia/commons/4/4f/Microsoft_Word_2013_logo.svg"
},
{
value: "MS-Excel",
label: "Microsoft Excel 2013",
image: "https://upload.wikimedia.org/wikipedia/commons/8/86/Microsoft_Excel_2013_logo.svg"
},
{
value: "MS-Outlook",
label: "Microsoft Outlook 2013",
image: "https://upload.wikimedia.org/wikipedia/commons/0/0b/Microsoft_Outlook_2013_logo.svg"
},
{
value: "MS-PowerPoint",
label: "Microsoft Word 2013",
image: "https://upload.wikimedia.org/wikipedia/commons/b/b0/Microsoft_PowerPoint_2013_logo.svg"
},
{
value: "MS-Access",
label: "Microsoft Access2013",
image: "https://upload.wikimedia.org/wikipedia/commons/3/37/Microsoft_Access_2013_logo.svg"
},
{
value: "Adobe-PSP",
label: "Adobe Photoshop CC",
image: "https://upload.wikimedia.org/wikipedia/commons/a/af/Adobe_Photoshop_CC_icon.svg"
},
{
value: "Adobe-LR",
label: "Adobe Lightroom CC",
image: "https://upload.wikimedia.org/wikipedia/commons/5/56/Adobe_Photoshop_Lightroom_Classic_CC_icon.svg"
},
{
value: "Adobe-PRM",
label: "Adobe Premiere Pro CC",
image: "https://upload.wikimedia.org/wikipedia/commons/5/58/Adobe_Premiere_Pro_CS6_Icon.png"
},
{
value: "Adobe-ACR",
label: "Adobe Acrobat",
image: "https://upload.wikimedia.org/wikipedia/commons/0/0b/Adobe_Acrobat_v8.0_icon.svg"
},
{
value: "Adobe-ILS",
label: "Adobe Illustrator CS6",
image: "https://upload.wikimedia.org/wikipedia/commons/d/d8/Adobe_Illustrator_Icon_CS6.png"
}
];
$(function() {
$("#search1").autocomplete({
source: products,
minLength: 3,
open: function() {
var $li = $("<li>");
var $link = $("<a>", {
href: "#",
class: "see-all"
}).html("See All Results").click(function(e) {
e.preventDefault();
$("#search1").autocomplete("option", "minLength", 0);
$("#search1").autocomplete("search", "");
}).appendTo($li);
$li.appendTo($('.ui-autocomplete'));
},
select: function(event, ui) {
event.preventDefault();
$("#search1").autocomplete("option", "minLength", 3);
},
focus: function(event, ui) {
event.preventDefault();
}
}).data("ui-autocomplete")._renderItem = function(ul, item) {
console.log(ul.content)
var $div = $("<div>").css("position", " relative");
$("<img>", {
src: item.image
}).css("height", "38px").appendTo($div);
$("<span>").css({
position: "absolute",
top: 0,
display: "inline-block",
"margin-left": "3px"
}).text(item.label).appendTo($div);
return $("<li>").append($div).appendTo(ul);
};
});
So you're using _renderItem() properly. I removed the Link from here based on the example you linked to. I moved this to the open callback as is shown in the example. I also switched some of your code. It wasn't wrong, I just prefer this method.
So the items get rendered so that the image and label show as desired. The the open call back adds a final link item that causes the a search for all items. See more: http://api.jqueryui.com/autocomplete/#method-search
Can be called with an empty string and minLength: 0 to display all items.
When an item is selected, the preferred minLength is returned to ensure that if the user starts a new search, it operates the same way it did the first time.
Update
http://jsfiddle.net/Twisty/wur8vok9/40/
Minor cleanup and better separation of code and style.
Hope this helps.

Related

JqGrid searchoptions with select2 existing value

I'm trying to integrate select2 for JqGrid filter form. I'm using JqGrid min 4.6 & Select2 min 4.0.1. The filter works fine but I'm unable to retrieve the value that has been set through select2 once the filter form is closed and reopened. i.e. dataInit e1 does not return the existing value of the select input. I must be doing something wrong?
JqGrid Column Model:
{
name: 'CurrencyID', hidden: true, search: true, stype: 'select', searchtype: 'number', searchoptions: {
searchhidden: true,
sopt: ['eq', 'ne'],
dataInit: function (el) {
intiGridFilterSelecr2Field(el, paramFromView.CurrencyOptions);
}
},
searchrules: { required: true }
},
Parameters:
#section scripts{
<script>
var paramFromView = {
CurrencyOptions: {
searchURL: '#Url.Action("GetCurrency", "Controller")',
detailURL: '#Url.Action("CurrencyDetailsJson", "Controller")',
idField: 'CurrencyID',
txtField: 'Description'
}
};
</script>
}
Select2 Helper:
function intiGridFilterSelecr2Field(element, options) {
var comboPageSize = 15;
var quietMillis = 200;
var placeHolderText = 'Choose...'
var defaults = {
searchURL: '',
detailURL: '',
idField: '',
txtField: ''
};
var options = $.extend({}, defaults, options);
var select2Element = $(element);
select2Element.select2({
width: 'element',
minimumInputLength: 1,
placeholder: placeHolderText,
ajax: {
url: options.searchURL,
dataType: 'json',
quietMillis: quietMillis,
cache: false,
data: function (params) {
return {
name: params.term,
page: params.page,
pageSize: comboPageSize
};
},
processResults: function (data) {
var more = (data.page * comboPageSize) < data.total;
var resultsArr = [];
for (var i = 0; i < data.result.length; i++) {
resultsArr.push({ id: data.result[i][options.idField], text: data.result[i][options.txtField] });
}
return { results: resultsArr, more: more };
}
},
}).each(function (index, element) {
var idCombo = $(this);
// The problem is that idCombo.val() is always empty.
// element:select2-hidden-accessible
if (idCombo.val() != null && idCombo.val().length > 0) {
$.ajax(options.detailURL, {
data: {
id: idCombo.val()
},
dataType: 'json',
cache: false
}).done(function (data) {
var optselected = select2Element.find('option').filter(function () { return this.value == data[idField] && this.text == data[txtField] && this.selected })
if (optselected == undefined || optselected.length == 0) {
var $optionContact = $("<option selected></option>").val(data[idField].toString()).text(data[txtField]);
var toBeRemoved = select2Element.find('option').filter(function () { return this.value == data[idField] });
if (toBeRemoved != undefined) {
toBeRemoved.remove();
}
select2Element.append($optionContact).trigger('change.select2');
}
});
}
});
}
When the filter is being set...
When Loading the existing filter. How do I pass this CurrencyID = 1 to select2 helper?
Update:
With Oleg's answer, I updated my code as below.
{
name: 'CurrencyID', hidden: true, searchtype: 'number', search: true,
stype: "select", searchoptions: {
searchhidden: true,
sopt: ["eq", "ne"],
dataUrl: paramFromView.CurrencyOptions.searchURL,
buildSelect: function (data) {
var obj = jQuery.parseJSON(data);
var i, options = [];
for (i = 0; i < obj.result.length; i++) {
options.push("<option value='" + obj.result[i][paramFromView.CurrencyOptions.idField] + "'>" +
obj.result[i][paramFromView.CurrencyOptions.txtField] + "</option>");
}
return "<select>" + options.join("") + "</select>";
},
noFilterText: "Any",
selectFilled: function (options) {
setTimeout(function () {
$(options.elem).select2({
width: 'element',
});
}, 0);
}
},
searchrules: { required: true }
},
I'm almost there with what I wanted to achieve. However I'm still facing some difficulties.
When the filter is initially loaded, value is selected on the dropdown but query value is empty. i.e. if the user clicks on the find button soon after the filter form is loaded, no filter will be set.
I still cannot get select2 styles working.
I can demonstrate how to use select2 with free jqGrid fork of jqGrid, which I develop. I get the demo from the README of the old version 4.14.1 (the current released version is 4.15.3) and modified it to demonstrate the usage of select2.
The main part of the code could be
stype: "select",
searchoptions: {
sopt: ["eq", "ne"],
...
selectFilled: function (options) {
setTimeout(function () {
$(options.elem).select2({
width: "100%"
});
}, 0);
}
}
See https://jsfiddle.net/Lae6kee7/2/. You can try to choose an option in the filter toolbar in "Shipped via" column and the open the search dialog. You will see that the select2 will have the same option selected.
If you would load the data via Ajax request posted by select2 than your code will be much more complex as it could be. It's important to understand that such way is really required only for really large set of possible value. I means the number of items larger as 100000 items for example. On the other side, the most use cases required less as 1000 options. In the case it would be more effective to load all the data as options of select and then convert the select to select2. select2, which uses local select works much more quickly from the users point of view.
The code will be easier in my opinion if you will use dataUrl instead of ajax option of select2. You can use dataUrl to return from the server all different values, which can be used in select2 and to use buildSelect to build <select> from JSON data returned from the server. The demo https://jsfiddle.net/Lae6kee7/23/ demonstrates that. I made the demo for JSFiddle, which supports Echo service (see here), which allows to simulate server responses. Your real code should contains mostly only dataUrl, buildSelect and the code of selectFilled, which I included above.
Additionally, I'd recommend you to consider to use <datalist> (see here for example), which could be good alternative to select2. All modern web browsers contains native support of <datalist> and thus <datalist> works very quickly. Try to search in the first Client column of my demos. You will see control, which will be very close to select2. Additional advantage of <datalist>: one will be able not search for only exact predefined values like test10, test11 or test12, but for substrings like 1. Compare
with
or
with

Jquery UI dialog, remove scrollbar if bootstrap columns are used

I created this fiddle to show my problem.
Isn't it possible to use bootstrap columns in a jquery ui dialog without getting this annoying horizontal scrollbar?
Soory, I don't know how to insert the fiddle code with the right depencies in the right way.
First think then write...
Just remove the "row" div and it works.
Look here.
Soory, I don't know how to insert the fiddle code with the right depencies in the right way.
Just add "style='overflow-x:hidden;'" to the dialog container div.
function CreateBusinessDialog(action, formId) {
var contId = 'dlgcont_' + GetUidString();
var container = document.createElement('div');
container.setAttribute('id', contId);
container.setAttribute('style', 'overflow-x:hidden;');
document.body.appendChild(container);
$('#' + contId).dialog({
autoOpen: false,
modal: true,
title: 'Create New',
width: '75%', //$(window).width() - 150,
height: $(window).height() - 150,
open: function (event, ui) {
$(this).load(action);
},
buttons: [{
text: 'Create',
click: function () {
var form = $('#' + formId);
form.validate();
if (form.valid()) {
//alert('valid');
form.submit();
}
}
}, {
text: 'Close',
click: function () {
$(this).dialog('close');
}
}],
close: function () {
container.parentNode.removeChild(container);
}
});
$('#' + contId).dialog('open');
}

TinyMCE render listbox items as html

I created a TinyMCE plugin and need the listbox items to display html. This is my plugin:
editor.addButton('icons', {
title: 'Foo',
text: 'Foo',
type: 'button',
onclick: function() {
editor.windowManager.open({
title: 'Foo',
width: 300,
height: 200,
body: [{
type: 'listbox',
label: 'Foo',
name: 'foo',
values: [{
title: '<em>Foo</em>', // <-- Mark save. Render as html.
value: 1
}],
}],
});
}
});
See also the fiddle: http://jsfiddle.net/allcaps/vqctac3d/
But the output looks like:
Expected:
How can I mark the list option title save so the contents is rendered as html?
Here is your updated snippet:
https://jsfiddle.net/mzvarik/1cwr07z6/55/
I was looking for same thing but listbox and it can be done like this:
(see fiddle for more)
editor.addButton('myshortcuts', {
type: 'listbox',
text: 'Vložit proměnnou',
values: self.shortcuts_data,
onselect: function() {
// do something
this.value(null); //reset selected value
},
onShow: function (event) {
var panel = $(event.control.getEl()),
button = event.control.parent().getEl();
var i=0;
panel.find('.mce-text').each(function(){
var item = $(this);
if (!item.next('.mce-menu-shortcut').length) {
// THIS WILL ADD HTML TO EXISTING MENU ITEM
item.after('<div class="mce-menu-shortcut">('+self.shortcuts_data[i].value+')</div>');
}
i++;
});
setTimeout(function(){
panel.css('width', 360);
panel.children().first().css('width', 360);
}, 5);
}
});
Here is screenshot:
Since noone else answered this question i will put the proposed solution/workaround from the comment into an answer.
Actually, it is not possible to insert html code using the tinymce way of listbox creation. But it is possible to style listboxes using css.
Due to the fact that listboxes and other tinymce UI elements get rendered dynamically it might be difficult to adress the correct html dom elements.
A workaround to this can be to exchange the listbox html after the listbox has been created. This is possible in case the ordering is known (and that is almost true).

JQUERYUI Autocomplete with json does not work

I have the following code using jqueryui and in the autocomplete box i see list but it doesn't show the content. The list has height of 0.
data is a json and i can see the data before the binding. Not sure what i am missing here.
$("#Stock").autocomplete({
dataType: "json",
source: data,
autoFill: true,
minLength: 1,
position: { my: "left to[", at: "left bottom", collision: "none" },
select: function (event, ui) {
alert(ui.item.Symbol)
},
open: function (e, ui) {
console.log($(".ui-autocomplete li").size());
},
search: function (e, ui) {
console.log("search returned: " + $(".ui-autocomplete li").size());
},
close: function (e, ui) {
console.log("on close" + $(".ui-autocomplete li").size());
$("#Stock").val("");
}
});
I have added the issue i am facing here.. Any help is much appreciated..
http://jsfiddle.net/BJGLf/
Currently you are passing [{Symbol: 'value'}] and the autocomplete is expecting ['value','value'] or [{ label: 'label', value: 'value' }, { label: 'label2', value: 'value2' }]. Refer to the API for the source formats.

jqgrid with custom column

I am using Jqgrid in my application. I wanted to create a column with 2 buttons. I want to have in column since the buttons may differ based on the data of the row. I googled it and I am able to found only creating a button using custom formatter option, but it appears only on double clicking a row or on edit of a row, but I want it to be displayed on column itself. Any help or link containing information will be appreciated. Below is my grid code.
Need to create an another column with buttons.
Edit:
var grid = $(gridId);
grid.jqGrid({
data: gridData,
datatype: "local",
gridview: true,
colModel: [
{
label: 'Employee Name', name: 'employeeName', width: 195, editable:true,
sortable:true, editrules:{required:true}
},
{
label: 'Address', name: 'address', width: 170, editable:true,
sortable:true,
editrules:{required:true}
},
{
label: 'Department', name: 'department', width: 120, editable:true,
sortable:true,
edittype:'custom',
editoptions: {
'custom_element' : populateReturnTypeAutocomplete,
'custom_value' : autocomplete_value
},
editrules:{required:true}
},
});
Okay add this to your colModal
{label: 'My Custom Column', name: 'custom', index:'custom' width: 120}
Now in gridComplete or loadComplete add this code
var grid = $("#grid"),
iCol = getColumnIndexByName(grid,'custom'); // 'custom' - name of the actions column
grid.children("tbody")
.children("tr.jqgrow")
.children("td:nth-child("+(iCol+1)+")")
.each(function() {
$("<div>",
{
title: "button1",
mouseover: function() {
$(this).addClass('ui-state-hover');
},
mouseout: function() {
$(this).removeClass('ui-state-hover');
},
click:
handle your click function here
}
).css({"margin-left": "5px", float:"left"})
.addClass("ui-pg-div ui-inline-save")
.attr('id',"customId")
.append('<span class="ui-button-icon-primary ui-icon ui-icon-disk"></span>')
.appendTo($(this).children("div"));
$("<div>",
{
title: "custombutton 2",
mouseover: function() {
$(this).addClass('ui-state-hover');
},
mouseout: function() {
$(this).removeClass('ui-state-hover');
},
click:
handle click here
}
).css({"margin-left": "5px", float:"left"})
.addClass("ui-pg-div ui-inline-custom")
.attr('id',"customButton2")
.append('<span class="ui-button-icon-primary ui-icon ui-icon-circle-check"></span>')
.appendTo($(this).children("div"));
Now these icons I'm adding here will be available with jquery ui.css and you will have to add one more function to your script which will get 'custom' column index for u in line first of above code.
var getColumnIndexByName = function(grid,columnName) {
var cm = grid.jqGrid('getGridParam','colModel'), i=0,l=cm.length;
for (; i<l; i+=1) {
if (cm[i].name===columnName) {
return i; // return the index
}
}
return -1;
};
I hope this helps.

Resources