Delaying select2 opening to fill it with data - javascript

I have a dropdown which I'm filling data by calling a function list(), which makes json calls and filters necessary data according to different parameters (It's very complex, and I'm not using the built in ajax feature).
Here's my code:
$("select.mission:visible").on("select2-opening", function() { list(); });
It works flawlessly, except for one little problem - updating the list is done while opening so the updated list doesn't show when you first open the dropdown. On the second open it shows the correct options.
I considered using select2-focus, but it's called twice, in the beginning and in the end. The second call repopulates the list and while the selected option is still highlighted, the value passes down as undefined.
The solution I look for is delaying the opening of the list to let it populate.
Any ideas in this direction or another?

it is a bit late for this question. I have the similar problem as you and I have solve it as below:
$("select.mission:visible").on("select2-open", function() {
$.getJSON("path-to-json", function(data) {
var results_data = [];
$.each(data.feed.entry, function(i, entry) {
results_data.push({'id':entry.id, 'text':entry.text})
});
// if your element select.mission:visible is select convert it to input:hidden
var id = $(this).attr('id') // get old id
var name = $(this).attr('name') // get old name
var oldVal = $(this).val() // get old value
$('select.missions').empty(); // empty select options
$(this).select2('distroy') // destroy current select2 obj
$(this).replaceWith(`<input type='hidden' class='mission' id='${id}' name='${name}'>`) // convert select element to input element
$(this).val(oldVal) // set new input element to previous value
$(this).select2({data:results_data}) // set new option items to new input element select2
$(this).select2('open') // force select2 element to open dropdown
});
});
Because I don't know which version of select2 you're using, but from your code, I assumed you are using select2 version 3.x. For more detail check it at https://select2.github.io/select2/

Related

Adding "values" to a texfield in jquery/js

When writing a new email, I've got a modal(pop-up window in boostrap) that shows a list of contacts. When I select (through checkboxes) a couple of contacts, the selected ones are written into a checkbox. Problem is I'm just writing the lastone I select instead of all of the selected ones.
If you need further explanation please ask. (Sorry for my english)
$("#tblContacto").on("click", ".ck", function(event){
if($(".ck").is(':checked')) {
selected_index = parseInt($(this).attr("alt").replace("Check", ""));
var contacto = JSON.parse(tbContactos[selected_index]);
$("#txtDestinatarios").val(contacto.Email);
} else {
$("#txtDestinatarios").val("");
}
});
Assuming that you want to add all E-Mails into a textfield with id txtDestinatariosthe cause of your Problem is the usage of the $("#txtDestinatarios").val(); function.
Calling val() with an argument sets (and thus overwrites) the value within the textfield. (See demo at http://api.jquery.com/val/#val2)
You would have to first retrieve the value of the textfield using code like var currentValue = $("#txtDestinatarios").val() and then add/remove the E-Mail from/to the string before setting the resulting string back as the value.
If you want to set all selected items in the checkboxes into Textfiled you can use the following line of code :-
$("#txtDestinatarios").val( $("#txtDestinatarios").val()+ ","+contacto.Email);

How do you replace the selection in medium-editor once it's lost?

I am trying to add an extension that replaces the existing link functionality in medium editor to allow me to have a filelist and other custom bits. The problem is that once I show modal and you make some change in it the original selection is lost. The example for inserting code, which looked to be the same thing the main script uses is this which I editing only so far as allowing a selection object to be passed in as a second param.
What I do is on button click show the modal, set some inputs, grab the selection from the base (same as window.getSelection()) save that to extension object. Then on clicking the save button in the modal I use the function from the code insert example, passing the selection. However the selection has changed, so I am guessing it's a reference or calculated everytime maybe, so I'm not sure how to make it work.
Here's code, I trimmed out the unrelated bits:
function MediumLink() {
var self = this;
this.parent = true;
//...button init
this.modalSubmit.addEventListener('click', function () {
//the linkSel is no longer what I set it to here
console.log(self.linkSel);
self.insertHtmlAtCaret('' + self.modalName.value + '', self.linkSel);
//... hide and reset modal
}, false);
//https://github.com/jillix/medium-editor-custom-html
this.insertHtmlAtCaret = function (html, sel) {
if (sel === undefined) {
sel = window.getSelection();
}
//..rest of this function is unchanged from example
};
}
MediumLink.prototype.onClick = function () {
var sel = this.base.selection;
if (sel.type === 'Range') { //trying to keep sel from changing since an empty selection would have a different type
//... set inputs in modal based on the selection
// sel is what I want at this point, what should be passed
console.log(sel);
this.linkSel = sel;
}
};
medium-editor does have support for this built in:
MediumEditor.saveSelection() // Stores the selection internally
MediumEditor.restoreSelection() // Re-applies the stored selection
From within your extension, since you're setting this.parent = true you can access this.base to call these methods:
this.base.saveSelection()
this.base.restoreSelection()
These built-in helpers should work fine as long as you don't make large alterations to the html (or more specifically the text value itself) between when the selection is saved and when the selection is restored.
Ok I think the problem boils down to this :
How do we save the selection and reproduce it if it is lost while we perform some other operation.
I dont know if there is an inbuilt medium editor function for it but I have encountered same problem and the short answer is to use Ranges and X-path to save selection.
Ranges are required to highlight the selection and X path to have selection accurately across all node and text.
Refer this :
How to calculate the XPath position of an element using Javascript?

JQuery & Javascript: Intermittant mis-matching of clicked div and returned div?

Thanks for giving this a look. I'll start with a quick image. Clicking on any of the red-boxed search results seems to return the <div> for the item directly above it.
Here I clicked on 1613 CAROUSEL CIR, but the event returned the id/content for the item representing 1612..
Sometimes it's even weirder, for example, every item following 1420 might point back to 1420. So it's not always a conflict with a <div> and it's immediate neighbor, although that's usually the case.
I've been unable to find any definite pattern in this behavior. Sometimes it's just one or two items in the list; sometimes most of the list is affected, with "a good portion" of results pointing to one particular div.
There's only one true consistency--typically the first several items work as expected, and short lists will be 100% correct. But really long lists (50+) are not necessarily worse than semi-long lists (20+).. :/
The code building the search results iterates over JSON data retrieved by a JQuery $.ajax() call, and this is the relevant code building the visible search results:
if( result.d.length > 0 )
{
var i=0;
for(i; i<result.d.length; i++)
{
// ..there's a bunch of irrelevant code here to set the map bounds..
// ..then I build the HTML using JQuery like this
//
var date = new Date();
var divID = "searchItemDiv" + date.getTime().toString();
var $searchItemDiv = $( "<div id='" + divID + "' class='searchItemDiv'>"+result.d[i].Description+"</div>" );
$searchItemDiv.data('itemData', result.d[i]);
$searchItemDiv.bind('click', onSearchItemClick);
$( "#searchResults" ).append($searchItemDiv);
}
}
While I don't suspect the event handler is the issue, the relevant code there looks like this:
function onSearchItemClick(event)
{
if( event.target.id.toString() !== '' )
{
// I clicked 1613, but event returned DIV with text of "1612"??
//
var item = $('#'+event.target.id.toString()).data('itemData');
alert( event.target.id.toString()+"\n"+
$('#'+event.target.id.toString()).text() );
// ..more irrelevant stuff to show a popup of property data..
}
}
FireFox, Chrome, and IE all demonstrate the same behavior, so it's not browser-specific.
I'm relatively sure this is not the product of a race condition during the render phase, but I'm not comfortable-enough with JavaScript to know that for certain.
I'm pretty baffled by this. FWIW, I'm a former Flex & C# developer and relatively new to JavaScript/JQuery development, so there may be a gotcha related JavaScript contexts and/or JQuery that I'm stepping into.
I would say, instead of binding the click function within a for-loop, just select all of the searchItemDiv's after the for-loop binds the data to them, and register a click function on all of them at once. You don't need a separate line to define variable i, just do it in the for statement. I also wouldn't try to generate random IDs with new Dates, that just seems unnecessary. Registering all click functionality at once will also make your click handler much simpler:
if( result.d.length > 0 )
{
for(var i = 0; i<result.d.length; i++)
{
// ..there's a bunch of irrelevant code here to set the map bounds..
// ..then I build the HTML using JQuery like this
// select the i'th searchItemDiv
$searchItemDiv = $($('.searchItemDiv')[i])
// give it the data
$searchItemDiv.data('itemData', result.d[i]);
$( "#searchResults" ).append($searchItemDiv);
}
// then register all the click handlers at once, very simple
$('.searchItemDiv').bind('click', function() {
var item = $(this);
alert(item.text());
});
}
--EDIT--
also, do the searchItemDivs already exist or are you trying to create them?
if you're trying to create them, you might want this in the for-loop instead:
for(var i = 0; i<result.d.length; i++)
{
// ..there's a bunch of irrelevant code here to set the map bounds..
// ..then I build the HTML using JQuery like this
// create a searchItemDiv
$searchItemDiv = $('<div class="searchItemDiv"></div>')
// give it the data
$searchItemDiv.data('itemData', result.d[i]);
$( "#searchResults" ).append($searchItemDiv);
}
I'm guessing that is what you want to do.
I think your problem depends on your searchItemDiv id.
Using the date doesn't ensure ids are unique so when you retrieve the object by id it will return an element (probably the first) with the same id.
Make sure to assign unique id on your elements.

Safari javascript object not updating

I have a piece of code that is working on all browsers except safari.
Basically I have an object called record.
record has properties, UserPhone, UserFax ...etc.
I also have a form with the same field names.
I update the object on the text field blur
$(this).on('blur', function() {
console.log($(this).val()); // shows the new value correctly
console.log($(this).attr('name')); // shows the right name correctly
record[$(this).attr('name')] = $(this).val();
console.log(record); // shows the record with the old value, should show the new value
updateDB();
});
The comments in the code to show what I'm getting in the console.
This code is working in other browsers.
Any idea?
This should work:
$(this).on('blur', function() {
console.log($(this).val()); // shows the new value correctly
console.log($(this).attr('name')); // shows the right name correctly
var key = $(this).attr('name'),
val = $(this).val();
record[key] = val;
console.log(record); // shows the record with the old value, should show the new value
updateDB();
});
There is an ambiguity in your scope, I assume.
Also, this fiddle resembles your code and I don't have any problems whatsoever.
EDIT: And the fiddle that addresses your problems. The takeaways from this should be to always avoid inline javascript and bind elements later.

Dropdown Menu using the 'storeLocator.Feature' in the Store Locator Library for Maps API

Is there any way of using a Dropdown Menu as opposed to the checkbox's that are used in the examples of the Store Locator Library for Maps API. The checkbox is a 'storeLocator.Feature' item.
Essentially I want the user to be able to select an item from the dropdown list and this instantly change the markers on the map.
I am very new to Javascript coding but experienced in CSS, HTML and other computer languages. I have followed the examples in the link fairly closely so you can assume my own code looks the same. –
Here is the section of code i think i have to edit:
DataSource.prototype.parse_ = function(csv) {
var stores = [];
var rows = csv.split('\n');
var headings = this.parseRow_(rows[0]);
for (var i = 1, row; row = rows[i]; i++) {
row = this.toObject_(headings, this.parseRow_(row));
var features = new storeLocator.FeatureSet;
features.add(this.FEATURES_.getById('Cafe-' + row.Cafe));
features.add(this.FEATURES_.getById('Wheelchair-' + row.Wheelchair));
features.add(this.FEATURES_.getById('Audio-' + row.Audio));
var position = new google.maps.LatLng(row.Ycoord, row.Xcoord);
var shop = this.join_([row.Shp_num_an, row.Shp_centre], ', ');
var locality = this.join_([row.Locality, row.Postcode], ', ');
var store = new storeLocator.Store(row.uuid, position, features, {
title: row.Fcilty_nam,
address: this.join_([shop, row.Street_add, locality], '<br>'),
hours: row.Hrs_of_bus
});
stores.push(store);
}
return stores;
};
Thanks.
you need to follow these steps:
set the featureFilter-option of the panel to false
(this will prevent the library from creating the checkboxes)
create a variable where you store all features for later use:
var features=view.getFeatures().asList();
this returns an array with all features
create the select-element
populate the select-element with the needed option-elements
iterate over the features-array created above and append an option for every item to the select .
The text to display inside the option you get by calling the getDisplayName()-method of the item.
add a change-handler to the select with the following callback:
function(){
view.set('featureFilter',
new storeLocator.FeatureSet(features[this.selectedIndex]));
view.refreshView();}
(where view is the storeLocator.View and features the array created in step#2)
5. put the select to the desired place inside the document
Hope i'm allowed to comment here as i found this question very useful for my implementation of store locator.
Dr Molle's solution in the JS fiddle is excellent however i've just noticed that the 'directions' functionality of the map no longer works. Could this easily be rectified? thanks
edit: easier than i thought. In the fiddle "featureFilter:" is set to 'false'. A div with the class="feature-filter" needs to be present in the code for the directions to appear, setting the value to 'true' shows the div (and checkboxes) so that directions work. Checkboxes were hidden in the stylesheet..
.storelocator-panel .feature-filter {
/*overflow: hidden;*/ display:none
}
This may be useful to someone

Categories

Resources