jQuery Combobox unsafe HTML insertion - jquery-ui

I tried to use jQuery combobox (fiddle) in my Mozilla Firefox addon. But AMO editors rejected my Addon after reviewing stating that my javascript does unsafe HTML insertion with unsanitized data. Parts of the code stated as unsafe all belong to the code on official jQuery Ui page for combobox. I am also writing the code below. Removing this piece of code throws error if I try to create a combobox.
It makes me wonder why combobox isn't already included in jQuery and why do I have to put this snippet inside my code? Am I doing anything wrong here. Alternatively Can someone suggest me how can I make this code taken from official jquery page safe and sanitized?
(function( $ ) {
$.widget( "ui.combobox", {
_create: function() {
var self = this,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "";
var input = this.input = $( "<input>" )
.insertAfter( select )
.val( value )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: text,
option: this
};
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
if ( !valid ) {
// remove invalid value, as it didn't match anything
$( this ).val( "" );
select.val( "" );
input.data( "autocomplete" ).term = "";
return false;
}
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
this.button = $( "<button type='button'> </button>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.insertAfter( input )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-button-icon" )
.click(function() {
// close if already visible
if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
input.autocomplete( "close" );
return;
}
// work around a bug (likely same cause as #5265)
$( this ).blur();
// pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
input.focus();
});
},
destroy: function() {
this.input.remove();
this.button.remove();
this.element.show();
$.Widget.prototype.destroy.call( this );
}
});
})( jQuery );

Related

JQuery UI autocomplete select on blur or on close

I would like to select the value from my input autocomplete on blur or on close.
I tried to put this in the function of the close parameter but it can't work :
close: function() {
$($(this).data('autocomplete').menu.active).find('a').trigger('click');
$(this).removeClass('ui-corner-top').addClass('ui-corner-all');
}
Anybody has a clue ?
Ok, thanks to Andrew Whitaker, I got this solution to select the first value automatically when leaving the autocompletion :
$.ui.autocomplete.prototype.options.autoSelect = true;
$( ".ui-autocomplete-input" ).live( "blur", function( event ) {
var autocomplete = $( this ).data( "autocomplete" );
if ( !autocomplete.options.autoSelect || autocomplete.selectedItem ) { return; }
autocomplete.widget().children( ".ui-menu-item:first" ).each(function() {
var item = $( this ).data( "item.autocomplete" );
autocomplete.selectedItem = item;
});
if ( autocomplete.selectedItem ) {
autocomplete._trigger( "select", event, { item: autocomplete.selectedItem } );
}
});
Updated code for jQuery UI - v1.12.1
$.ui.autocomplete.prototype.options.autoSelect = true;
$( ".ui-autocomplete-input" ).live( "blur", function( event ) {
var autocomplete = $(this).autocomplete('instance');
if (!autocomplete.options.autoSelect || autocomplete.selectedItem ) { return; }
autocomplete.widget().children( ".ui-menu-item:first" ).each(function() {
var item = $( this ).data('ui-autocomplete-item');
autocomplete.selectedItem = item;
});
if ( autocomplete.selectedItem ) {
autocomplete._trigger( "select", event, { item: autocomplete.selectedItem } );
autocomplete._value( autocomplete.selectedItem.value );
}
});

jqueryui Autocomplete. what m i doing wrong

so heres is the prob im calling two variables from the input and on the "#key" variable the last call in the database from "split( this.value );" makes it out put like this
//this is fine
touser: karen galante, jor monucha, wappa who,
//this needs to be
rnkey: karen galante,jor monucha,gdhdf9j7hd98fg7dfn,
// nappppaa8686f86df8,iuof79f79ds7h8j7kg70gfd70fg8dsf,gdhdf9j7hd98fg7dfn,
im new to jquery ui and iv been working on this code for a copple days now, any ideas
$(function() {
var availableTags = [
{
value: "iuof79f79ds7h8j7kg70gfd70fg8dsf",
label: "jor monucha",
desc: "the write less, do more, JavaScript library",
icon: "16.png"
},
{
value: "nappppaa8686f86df8",
label: "karen galante",
desc: "the write less, do more, JavaScript library",
icon: "16.png"
}, {
value: "gdhdf9j7hd98fg7dfn",
label: "wappa who",
desc: "the write less, do more, JavaScript library",
icon: "16.png"
},
];
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#tags" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "autocomplete" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 2,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
response( $.ui.autocomplete.filter(
availableTags, extractLast( request.term ) ) );
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
$( "#project" ).val( ui.item.label );
$( "#project-id" ).val( ui.item.value );
$( "#project-description" ).html( ui.item.desc );
$( "#project-icon" ).attr( "src", "images/" + ui.item.icon );
var hintkey = split( this.value );
// remove the current input
hintkey.pop();
// add the selected item
hintkey.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
hintkey.join( ", " );
hintkey.push( "" );
$( "#key" ).val(hintkey);
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.label );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );

How can I add and show a new select value to a jquery combo box autocomplete

I'm using jquery UI autocomplete combobox which is populated with a select box.
Here is the code:
$.widget( "ui.combobox", {
_create: function() {
var input,
self = this,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "",
wrapper = this.wrapper = $( "<span>" )
.addClass( "ui-combobox" )
.insertAfter( select );
input = $( "<input>" )
.appendTo( wrapper )
.val( value )
.addClass( "ui-state-default ui-combobox-input" )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: text,
option: this
};
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
if ( !valid ) {
// remove invalid value, as it didn't match anything
$( this ).val( "" );
select.val( "" );
input.data( "autocomplete" ).term = "";
return false;
}
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
$( "<a>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.appendTo( wrapper )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-combobox-toggle" )
.click(function() {
// close if already visible
if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
input.autocomplete( "close" );
return;
}
// work around a bug (likely same cause as #5265)
$( this ).blur();
// pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
input.focus();
});
},
destroy: function() {
this.wrapper.remove();
this.element.show();
$.Widget.prototype.destroy.call( this );
}
});
Here is a screenshot showing the form:
When a user clicks 'add Author' a modal loads for them to create a new Author model object. I want to add and show the newly created author in the jquery UI combobox.
I'm using Rails 3.2 and use a create.js.erb file to control the response from creating the object.

jquery ui autocomplete pass a variable

I m using jquery UI for getting suggestions of friend names and id, but the problem is I am not able to pass user id using autocomplete json function .
$(function() {
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split(term).pop();
}
$( "#recipient" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).data( "autocomplete" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
source: function( request, response ) {
var attm= $('.USERID').val();
$.getJSON( "modules/messages/sql.php", {
term: extractLast( request.term ),
}, response );
},
search: function() {
// custom minLength
var term = extractLast( this.value );
if ( term.length < 2 ) {
return false;
}
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( ", " );
var prollNos = $('#recipientid').val()
$('#recipientid').val(prollNos + ui.item.id + ", ");
return false;
}
});
});
in which i am trying to pass a: $('.USERID').val() as user id , can anyone help me out?
I achieve something similar by GET. I use jquery-ui-autocomplete, as source I use: "source.php?param=something". So the final request my source page gets is "source.php?param=something&term=blabla"

jQuery UI autocomplete combo box issue

I'm trying to use this example http://jqueryui.com/demos/autocomplete/#combobox . But it shows blank option by default. instead of "Select one...". How to fix that problem?
And one more question: I don't use "show underlying menu" buton as in show in example. Is there any unused pc of code for that button in JS code?
it shows blank option by default. instead of "Select one...". How to fix that problem?
The reason this is occurring is this piece of code in the _create function:
value = selected.val() ? selected.text() : "";
Just change the false portion of the ternary to say "Select One":
value = selected.val() ? selected.text() : "Select one...";
Here's the modified widget for reference:
$.widget( "ui.combobox", {
_create: function() {
var self = this,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "Select One...";
var input = this.input = $( "<input>" )
.insertAfter( select )
.val( value )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: text,
option: this
};
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
if ( !valid ) {
$( this ).val( "" );
select.val( "" );
input.data( "autocomplete" ).term = "";
return false;
}
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
this.button = $( "<button type='button'> </button>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.insertAfter( input )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-button-icon" )
.click(function() {
if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
input.autocomplete( "close" );
return;
}
$( this ).blur();
input.autocomplete( "search", "" );
input.focus();
});
},
destroy: function() {
this.input.remove();
this.button.remove();
this.element.show();
$.Widget.prototype.destroy.call( this );
}
});
I don't use "show underlying menu" buton as in show in example. Is there any unused pc of code for that button in JS code?
Yes, you're safe to remove that button. In fact, all you need is a select element to initialize the widget on.
Here's an example of the combobox without a button and with "Select one..." as the default text: http://jsfiddle.net/andrewwhitaker/MgjRy/

Resources