create dynamic selector in jquery plugin - javascript

I am creating a jquery plugin and my html is like
<select class="filter">
<option value="">Select Brand</option>
<option value="value1">value1</option>
<option value="value2">value2</option>
<option value="value3">value3</option>
</select>
my plugin code is like
(function( $ ) {
$.fn.filterCategory = function( options ) {
$(".filter option").each(function(){
var text = $(this).text();
$(this).attr("data-val",text);
});
// other code...
};
}( jQuery ));
and i call it like
$("select.filter").filterCategory();
the problem is if i want to call this plugin by id like
$("select#filter").filterCategory();
or by other class or id like
$("select.new_filter").filterCategory();
$("select#new_filter").filterCategory();
then the html will be like
<select id="filter">
<option>...</option>
</select>
then i will have to make changes on my plugin. It means it works only for .filter only. How can i make this code dynamic
$(".filter option").each(function(){ ... }

You need to use the this keyword to reference the elements that the plugin was intialised on:
(function($) {
$.fn.filterCategory = function(options) {
$(this).find('option').each(function() {
var text = $(this).text();
$(this).attr('data-val', text);
});
// other code...
};
}(jQuery));
You should also ensure you return a jQuery object from your plugin, assuming you wish to maintain the chaining pattern that jQuery uses. Finally note that you can simplify the each() loop to just call attr() only:
$(this).find('option').attr('data-val', function() {
return $(this).text();
});
This is of course assuming that you need to have the data-val attribute within the DOM. If not, I'd suggest using data() instead to use jQuery's internal cache.

Related

jquery wait on change event

With jQuery I built a dynamic form; when the first select-input (named category) changes a second select-input (named subcategory) appears with sub-select items. And this works perfect now.
When a specific url parameter is given I want to auto-fill in the form after the page is ready.
$(document).ready(function () {
// initialize defaults
var category = getUrlParameter('category');
var subcategory = getUrlParameter('subcategory');
if (category && subcategory) {
$("select#category").val(category).change();
$("select#subcategory").val(subcategory).change();
}
});
Where getUrlParameter is a helper function I copied from Sameer Kazi.
Currently the first select-input is filled in, the second select-input is generated but not filled in. So actually, the change command needs to wait untill the first change command is ready.
You can using jQuery's .when() function, which handles an asynchronous function first before .then() is called.
$.when($("select#category").val(category).change()).then(function() {
$("select#subcategory").val(subcategory).change();
});
Here below is a small example using those two functions. I have added a console.log function to the select change event handlers so that you can follow what happens.
$("select#category").on('change', function() {
console.log('[on change] category changed');
$("select#subcategory").show();
});
$("select#subcategory").on('change', function() {
console.log('[on change] subcategory changed');
});
$(document).ready(function () {
// initialize defaults
var category = 1;
var subcategory = 2;
if (category && subcategory) {
$.when($("select#category").val(category).change()).then(function() {
console.log('[then] activating subcategory');
$("select#subcategory").val(subcategory).change();
});
}
});
select#subcategory {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="category">
<option>...</option>
<option value="1">value 1</option>
<option value="2">value 2</option>
</select>
<select id="subcategory">
<option value="1">subvalue 1</option>
<option value="2">subvalue 2</option>
</select>
setTimeout(function(){
$("select#subcategory").val(subcategory).change();
},300);
maybe this?
Wait 300 ms till make other change. I guess its enough to have a first one done :)
$("select#category").on("load",function(){
$("select#subcategory").val(subcategory).change();
});
Maybe this will work if I got your problem
Maybe you can listen for event onChnage
$("select#category").on("change",function(){
$("select#subcategory").val(subcategory).change();
});
also instead of $("select#category").val(category).change();
try
$("select#category").val(category).trigger('change');

How I use this jquery function correctly?

I have a dropdown and its populating with dynamic data. Here I have used a function to call ajax and get the dynamic data.
This is how I create this function:
function Banks($selecter, selected) {
// my stuff ----
}
I am using it like this when the document ready:
Banks($('#DropDownEdit'));
HTML look like this:
<select id="DropDownEdit" name="bank_one" data-id="4"></select>
Now I need to get data-id value to the function when document is ready.
I tried it something like this:
$(document).on('change', '#DropDownEdit', function(){
var ID = $(this).data('id');
Banks($('#DropDownEdit'), ID);
});
But It doesn't work for me. Can anybody tell me how I do this rightly?
Your HTML markup seems to be all wrong. An empty select tag is not a valid markup and onchage never triggers for an empty select. The select tag must have at least one option inside.
<select id="DropDownEdit" name="bank_one" data-id="4">
<option value="one">1</option>
<option value="two">2</option>
<option value="three">3</option>
</select>
Try this.
$(document).ready(function(){
var ID = $('#DropDownEdit').data('id');
})
Try the FIDDLE
I have updated the event delegation assignment as following and it works
function Banks($selecter, selected) {
//alert(selected);
$selecter.append('<option>1</option><option>2</option><option>3</option><option>4</option>')
// my stuff ----
}
$(function () {
Banks($('#DropDownEdit'), $('#DropDownEdit').data('id'));
$('#DropDownEdit').on('change', function () {
var ID = $(this).data('id');
alert(ID);
Banks($('#DropDownEdit'), ID);
});
});
Hope it works for you
You need to get data-id value to the function when document is ready.
try to use $(document).ready();
$(document).**ready**(function(){
var ID = $('#DropDownEdit').data('id');
Banks($('#DropDownEdit'), ID);
});
hope this help.

Bootstrap selector for multiselect- select all option

So what i need is an select all option in multiple bootstrap selector as an option so i just create a select as
<select class="form-control selectpicker" multiple>
<option value="all">All</option>
<option value="1">Dog</option>
<option value="2">Cat</option>
<option value="3">Tiger</option>
</select>
And when i click All it will remove all other options except all, and if i click any other than All then it need to remove all options
What i tried is like
$(".selectpicker").change(function(event){
if ($( this ).find("option:first").is(':selected')) {
$( this ).find("option").prop('selected', false);
$( this ).find("option:first").prop('selected', true);
} else {
$( this ).find("option:first").prop('selected', false);
}
});
But once All clicked then always all is activated and nothing can be clicked, i even tried to get value on onclick event but due to bootstrap selectpicker i can able to get it?
Any tricks to made this possible? i can do this with static variable for one selecpicker but can't able accomplish with multiple selectpicker in a form.
New edit
Here is a working DEMO
$('.selectpicker').selectpicker();
var all = $('option[value=all]');
$('.selectpicker').change(function() {
var all = $('option[value=all]');
var thisVal = all.html();
if (all.is(':selected')) {
$('.selectpicker').selectpicker('deselectAll');
$('ul.dropdown-menu > li[rel=0]').addClass('selected');
$('span.filter-option').html(thisVal);
} else {
$('ul.dropdown-menu > li[rel=0]').removeClass('selected');
}
});
I think you can do something like
$("#multiple-select option").prop("selected", "selected");
$('#multiple-select').selectpicker('refresh');
Must use prop.

getText() not working on a select from dropdown

I have a page with a select box with various options, and I'm writing an acceptance test to check that when the page first loads, the correct option is selected. I hoped to do this using WebdriverJs but for some reason getText() is always returning an empty string.
On load, I would hope that the page looks like this:
<select class='nav-menu'>
<option value="global" selected="selected">WORLDWIDE</option>
<option value="us">USA</option>
<option value="uk">UNITED KINGDOM</option>
<option value="au">AUSTRALIA</option>
<option value="ca">CANADA</option>
<option value="de">GERMANY</option>
<option value="es">SPAIN</option>
<option value="fr">FRANCE</option>
</select>
I'm then trying to find out the value of the current selected option as follows:
browser.findElement(webdriver.By.css('.nav-menu option[selected="selected"]')).getText().then(function(selectedText){
console.log("selectedText: " + selectedText);
next();
});
However, this is also logging out an empty string.
Calling the JavaScript equivalent using the Chrome developer tools is returning "WORLDWIDE" - any thoughts what is wrong with this?
I don't use WebDriverJS, so I can't prove my theory, but I guess it's because Selenium getText() will only work for visible elements?
Try using getAttribute("textContent")
Try clicking on .nav-menu first, then use getText()
Hmm, well some playing around suggests that the CSS select was working okay, but the getText() method wasn't working.
For the moment, I've got it working use the innerHTML attribute:
browser.findElement(webdriver.By.css('.nav-menu option[selected="selected"]')).getAttribute('innerHTML').then(function(selectedText){
console.log("selectedText: " + selectedText);
next();
});
So CSS selector seems reliable, but I will also try out the textContent suggestion from user1177636.
I've found selecting 'option' elements via css + the selected attribute to be unreliable.
The following works for me:
var By = require('selenium-webdriver').By;
var dd = driver.findElement(By.id('myId'));
dd.findElements(By.tagName('option')).then(function (options) {
options.forEach(function(option) {
option.isSelected().then(function(selected) {
if (selected) {
option.getText().then(function(text) {
console.log(text);
done(); //mocha async callback
});
}
});
});
});
You could wrap this into a function, something like:
var wd = require('selenium-webdriver'),
By = wd.By;
function getFirstSelected(selectList) {
var d = wd.promise.defer();
selectList.findElements(wd.By.tagName('option')).then(function (options) {
options.forEach(function(option) {
option.isSelected().then(function(isSelected) {
if (isSelected) {
d.fulfill(option);
}
});
});
});
return d.promise;
}
and use it like:
var sl = driver.findElement(wd.By.id('myId'));
getFirstSelected(sl).then(function(option) {
option.getText().then(function(text) {
console.log(text);
done();
});
});

How to implement jQuery val() for a span?

I have a few select elements that are grouped by a span. I'm creating a plugin to do some interaction with the elements. Now I would like to give my users the support of the val() function, so that they are able to get or set the 'value' of my span. Setting the value will result in the select box element to change en getting the value will result in the addition of the selectbox values.
Basically I would like my plugin to add the support for the val() method. Any ideas on how to implement this?
Code
<span id="test">
<select id="one">
<option value="1">1</option>
<option value="2">2</option>
</select>
<select id="two">
<option value="1">1</option>
<option value="2">2</option>
</select>
</span>
Challange
Get the following code to work: $('#test').val('1:1'); and $('#test').val().
This is not a full plugin and I did not override val() but it should do what you want.
$.fn.value = function(value) {
if (value) {
var s = value.split(':');
for ( var i = 0; i < s.length; i++ ) {
this.find('select').eq(i).val(s[i]);
}
} else {
var result = [];
this.find('select').each( function( index, item ) {
result.push($(item).val());
});
return result.join(':');
}
}
$(function() {
$("#test").value("2:2");
alert($("#test").value());
});
You can try it at http://jsfiddle.net/QBSWm/1/
I don't think its a good idea to mess with jQuery like this, and there may be some typing errors, but here you go:
var oldVal = jQuery.fn.val;
jQuery.fn.extend({
val: function(value) {
// replace class check below with something related to your span
if (this.length == 1 && this.is('span.my-custom-class')) {
if (arguments.length == 0) {
// below is just a sample, traverse
// child selects like in DanielB's answer
// and return the value you expect
return this.attr('justsomesample');
}
else {
this.attr('justsomesample', value);
return this;
}
};
return oldVal.apply(this, arguments); }});
});
Look at the InputMask jquery plugin. What they do is to store original jquery val() function in a variable and replace it with their own. Then you will receive the call first, you can check if the element is span, and if so return it otherwise call the original function.
var originalVal = $.fn.val;
$.fn.val = function(params){
// if span then return your logic
// otherwise call originalVal
}
You can use the .text() JQuery function instead of .val() JQuery function to change your span.
It's not a good iead to override .val(), but if you really want a .val() like method for span, you could just add following code :
$.fn.sval = function(value) {
if(!value)
return $(this).html();
else
return $(this).html(value);
}
and then, to use it, just like .val() :
// Get value
alert($('#test').sval());
// Set value
$('#test').sval("yo");

Categories

Resources