<select>'s not updating with Semantic UI - javascript

We have a popup containing a form with quite a few <select> tags. In some cases a <select> will appear on the page when it loads with no <option> tags inside, and it will be filled in later. Some already have <option>s defined. In every case, <option>s could be added or removed from the <select>s. We are using Semantic UI and defining the <select>s like this:
<select id="select1" class="ui dropdown"></select>
It is not updating the dropdowns it creates (the "menu") when the underlying <select> changes. Is there something we need to call when <option>s are added or removed?
UPDATE:
I tried this:
$('#select1').dropdown('refresh')
and the semantic UI menu did not update.
UPDATE 2
In some cases, the <options>s are "added" or "removed" by just changing their display to none instead of actually removing them from the <select>. In other cases they are actually added or removed. Can Semantic UI handle both of these cases?

I decided to move ahead and created a proof-of-concept to see if there was a way to handle this. I created a mutationobserver to look for changes in the attributes of every in the popup and have the semantic ui "menu" match the display property of the associated . It appears to be working.
function create_select_mo()
{
//create observer
var observer = new MutationObserver(function(mutations){
//console.log(mutations)
//get changed element in select
var target_el = mutations[0].target
if(!gel(target_el.parentNode))
{
return false
}
//find the changed <select>
var sel = target_el.parentNode
//make sure the parent is a <select>
if(sel.nodeName != 'SELECT')
{
return false
}
//get <select> wrapper created by semantic ui
var wrapper = sel.parentNode
//find the associated semantic menu
var cur_menu = $(wrapper).children('.menu')
if(gel(cur_menu))
{
//get corresponding element to target element in semantic menu
var menu_el = $(cur_menu).children('div[data-value=' + target_el.value + ']')[0]
//change the menu element to match the style of the <select> element
if(menu_el)
{
menu_el.style['display'] = target_el.style['display']
}
}
})
//initialize config to look for changes to attributes
var observer_config = {
attributes: true,
}
//set observer on each <option>
var target_nodes = gel('my_popup').querySelectorAll('option') //document.body
for(var x=0;x<target_nodes.length;x++)
{
observer.observe(target_nodes[x], observer_config)
}
}
function gel(el)
{
if(document.getElementById(el))
{
return document.getElementById(el)
}
else if($(el).get(0))
{
return $(el).get(0)
}
else if((typeof el == 'object') && (Object.keys(el).length > 0))
{
return el
}
else
{
//console.log(el + ' not found')
return false
}
}

Related

Removing multiple select options and replace with new ones

I have a select tag like :
<span id="reportProjectSelector">
<span>Reporting Project:</span>
<select id="reportProjectDropdown" onChange="loadChartWithData();" multiple="multiple"></select>
</span>
and
$(function() {
$('#reportProjectDropdown_${widgetId}').multiselect({
includeSelectAllOption: true
});
});
Here I have multiple dropdown chain of other dropdowns which are parents of 'reportProjectDropdown'. For simplicity let's consider just one 'Project'. So now we have 'Projects', on change of which 'Reporting Projects' filter is triggered. Currently the Reporting project filter doesn't change and replace new values (basically null or no values which are replaced by a value like 'No Reporting Projects' in the dropdown)
I have tried removing the previous values but with no luck. Here is the function that I am expecting will do the job.
function setDependentProjects (data, widgetId) {
$('#reportProjectDropdown').find('option').remove().end();
if(jQuery.isEmptyObject(data)) {
let newOption = new Option("No Projects", 0, true, true);
$('#reportProjectDropdown').append(newOption);
} else {
let selected = true;
for(let key in data) {
selected = "${defaultDependentProject}" == data[key];
let newOption = new Option(data[key], key, selected, selected);
$('#reportProjectDropdown').append(newOption);
selected = false;
}
}
loadChartWithData_${widgetId}(); //renders data as per the previous filters
}
Am I missing something or removing the elements incorrectly ?
You need to refresh the jQuery multiselect instance after every change. You can do that by using $('#reportProjectDropdown').multiSelect('refresh');
See also the documentation: jQuery multiselect

SAPUI5 TreeTable: User Interaction set to "true" when event fired by code

When selecting a row in my SAPUI5 tree table I have to make sure that
all existing selections are removed
check if selected row has children and if so, select the item and all its children
To do that I use a function that gets called on the rowSelectionChange-Event of my table:
onRowSelectionChange: function(oEvent) {
if (oEvent.getParameters().userInteraction)
var oTable = oEvent.getSource();
var oObject = oEvent.getParameters().rowContext.getObject();
var iIndex = oEvent.getParameters().rowIndex;
// Check if row was selected or deselected
if (oTable.isIndexSelected(iIndex)) {
// Deselect other items
oTable.clearSelection();
// Select row again
oTable.addSelectionInterval(iIndex, iIndex);
// Check if object has children
if (oObject.content) {
//Select child rows here
} else {
// Do stuff
}
} else {
// Do stuff
}
}
}
As you can see the first thing I do is to check if the selection change's origin was an explicit user interaction, because, of course, clearing the selection and then adding the selection for the child rows will call the function again.
My problem is now, that when clearSelection() calls my function, the userInteraction-parameter is again set to true, despite not being an explicit user interaction. Am I missing something here?
Thank you!

Kendo UI Web - MultiSelect: select an option more than once

I'm currently facing a problem with the Kendo UI MultiSelect widget for selecting an option more than once. For example, in the image below I want to select Schindler's List again after selecting The Dark Knight, but unfortunately the MultiSelect widget behaves more like a set than an ordered list, i.e. repetitive selection is not allowed. Is there actually a proper way to achieve this? Any workarounds?
That's the intended behavior of the multi-select control and there is no simple way to make it do what you want using the available configuration options. Possible workarounds are ...
Creating a custom multi-select widget
Something like this should work (note that I haven't tested this much - it lets you add multiples and keeps the filter intact though):
(function ($) {
var ui = kendo.ui,
MultiSelect = ui.MultiSelect;
var originalRender = MultiSelect.fn._render;
var originalSelected = MultiSelect.fn._selected;
var CustomMultiSelect = MultiSelect.extend({
init: function (element, options) {
var that = this;
MultiSelect.fn.init.call(that, element, options);
},
options: {
name: 'CustomMultiSelect'
},
_select: function (li) {
var that = this,
values = that._values,
dataItem,
idx;
if (!that._allowSelection()) {
return;
}
if (!isNaN(li)) {
idx = li;
} else {
idx = li.data("idx");
}
that.element[0].children[idx].selected = true;
dataItem = that.dataSource.view()[idx];
that.tagList.append(that.tagTemplate(dataItem));
that._dataItems.push(dataItem);
values.push(that._dataValue(dataItem));
that.currentTag(null);
that._placeholder();
if (that._state === "filter") {
that._state = "accept";
}
console.log(this.dataSource.view());
},
_render: function (data) {
// swapping out this._selected keeps filtering functional
this._selected = dummy;
return originalRender.call(this, data);
this._selected = originalSelected;
}
});
function dummy() { return null; }
ui.plugin(CustomMultiSelect);
})(jQuery);
Demo here.
Using a dropdown list
Use a simple dropdown list (or ComboBox) and bind the select event to append to your list (which you have to create manually).
For example:
var mySelectedList = [];
$("#dropdownlist").kendoDropDownList({
select: function (e) {
var item = e.item;
var text = item.text();
// store your selected item in the list
mySelectedList.push({
text: text
});
// update the displayed list
$("#myOrderedList").append("<li>" + text + "</li>");
}
});
Then you could bind clicks on those list elements to remove elements from the list. The disadvantage of that is that it requires more work to make it look "pretty" (you have to create and combine your own HTML, css, images etc.).

filtering only previously unselected <select> options qith JQuery

Previously I asked how to do this and was directed to this:
<script>
jQuery.fn.filterByText = function(textbox) {
return this.each(function() {
var select = this;
var options = [];
$(select).find('option').each(function() {
options.push({value: $(this).val(), text: $(this).text()});
});
$(select).data('options', options);
$(textbox).bind('change keyup', function() {
var options = $(select).empty().scrollTop(0).data('options');
var search = $.trim($(this).val());
var regex = new RegExp(search,"gi");
$.each(options, function(i) {
var option = options[i];
if(option.text.match(regex) !== null) {
$(select).append(
$('<option>').text(option.text).val(option.value)
);
}
});
});
});
};
</script>
(http://www.lessanvaezi.com/filter-select-list-options/)
When I use this filter on the select box it filters both the unselected AND the selected. I'd like it to ONLY filter the unselected because if a user wants to ammend the selections and filters again, the previously selected items go away - unless they meet the filter criteria.
I'm not that good at JavaScript or JQuery and can't understand how I might tell the above script to ignore options that are ":selected" but filter all else.
Here's a jfiddle if it helps: http://jsfiddle.net/UmKXy/ I'd like option one and two to remain selected and in the list when user begins to type.
Thanks for help!
The solution you had would not work with selected elements because he created an array of options at the start and then matched those options against the regex(Without regards to what is actually selected). I've used spans to hide options in the past and created an example for you to see how it works. Here is the link : http://jsfiddle.net/rD6wv/
Here is the code
$(function() {
$("#filterByText").bind('keyup',function(){
var search = $.trim($(this).val());
var regex = new RegExp(search,"gi");
$("#filez").find('option').each(function(){
if(!$(this).is(':selected')){
if($(this).val().match(regex) === null) {
$(this).wrap('<span>');
}else if($(this).parent().is('span')){
$(this).parent().replaceWith($(this));
}
}
});
});
});
You simply need to loop through all the options of the select when you type in the textbox.
You then check if it is selected, if it is you do nothing, else you check if it matches the search filter, if it does you wrap it in a span, making it invisible, else it means you need to see it, so you check if it is already wrapped in a span, and in that case you replace it with the option so you can see it again.
to selected the non selected options, use this:
$('option:not[selected]') or $('#myselect > option:not[selected]')
to remove them, use this:
$('option:not[selected]').remove();
in css, :not filters for opposite of what comes in the curved brackets.
and [] is attribute selector.
so :not[selected] means: does not have an attribute whose key is "selected"

Get numerical value from parent with id like 'post-1' and use it in jQuery function

I'm trying to figure out the following.
I have following jQuery code:
var as = "";
var bPlay = 0;
audiojs.events.ready(function() {
as = audiojs.createAll();
$(".audiojs .play-pause").click(function() {
var e = $(this).parents(".audiojs").index(".audiojs");
$.each(as, function(t, n) {
if (t != e && as[t].playing) {
as[t].pause()
}
})
bPlay = !bPlay;
if (bPlay == 1) {
$(".bar").each(function(i) {
fluctuate($(this));
});
} else {
$(".bar").stop();
}
})
});
In a nutshell it preforms list of things when someone clicks particular .audiojs instance on a page. 1) checks if there is any other instance playing, if there is pauses it. And if it is playing applies fluctuate function to elements on a page that have class="bar". This is the issue! I don't want to apply it to all .bar's on a page, but only to a specific group that is associated with particular .audiojs instance (the one that is being clicked and is playing).
I thought of the following solution. Each .audiojs instance is inside a div tag that has id like "post-1", "post-2" etc.. where numerical value is post id from database. I can add this numerical id to bar, so it would be like bar-1, bar-2 etc... However after this I'm having issues.
For javascript to work I need to retrieve numerical value from "post-[id]" associated with audiojs instance that is being clicked and than store it somehow, so I can use it like this afterwards
bPlay = !bPlay;
if (bPlay == 1) {
$(".bar-[value retrieved from post-...]").each(function(i) {
fluctuate($(this));
});
} else {
$(".bar-[value retrieved from post...]").stop();
}
Could someone explain to me how it can be achieved?
Honestly, the easiest way would be to stick it in a custom data-* attribute on the <div id="post-X"> element, like so:
<div id="post-1" data-bar="bar-1">...</div>
Then, you said your .audiojs element is inside that <div>, so just go from this inside the event handler to that <div> element (using .closest()) and get the value of it:
var barId = $(this).closest('[id^="post-"]').attr('data-bar');
Then when you need to use it:
$("." + barId).each(function(i) {
fluctuate($(this));
});
Instead of embedding the value in a class or ID, use a data-* attribute:
<div class="audiojs" data-fluctuate-target="bar-1">
<button type="button" class="play-pause">
<!-- ... -->
</button>
</div>
<div class="bar-1">
<!-- ... -->
</div>
In your click event handler, use the following to fluctuate or stop the correct elements:
var fluctuateClass = $(this).closest('.audiojs').attr('data-fluctuate-target');
$('.' + fluctuateClass).each(function () {
if (bPlay == 1) {
fluctuate($(this));
} else {
$(this).stop();
}
});

Categories

Resources