cross browser issues jquery dropdown menu - javascript

Ok I made a site a while back and always had issues with the menu system is needed. Basically you click a location on a map, then it displays the list of sub locations in the dropdown menu to the right. These are always their they just chance to display based on the options class.
I have put the site at shiftera.co.uk so you can see it their.
The issue first.
1) IE - The list never filters out, it displays all results all the time regardless of class.
2) Chrome - The dropdown is sometimes squashed showing 1 result and hiding the others you need to use up/down arrows to change, sometimes it shows 3, sometimes 4.
3) Firefox - The list displays in 1 long row, not like a usual dropdown.
I think the issue is more of a css problem or multitude of css problems.
An example of the map link is
Scotland
The dropdown list although not seperated is generated from the database and appears as below
<option value='AB25 1UH' class="Scotland">Aberdeen</option><option value=' WA14 4DW' class="Northwest">Altrincham</option>
As you can see, some have the space before some don't. The dropdown has the id of apick and Im using css below to hide it on load.
#apick { display: none; }
Here is the javascript to display the correct items based on map click.
//<![CDATA[
$(document).ready(function(){
$('.areaselect').on('click', function(event){
$('#apick').css('display','inline');
var id = $(this).attr('id')
$('#apick option').not('.'+id).css('display','none');
$('.'+id).css('display','inline').first().attr('selected','selected');
event.preventDefault();
});
}); //]]>
This has been driving me mad for a long time now, it seem's if i fix 1 issue another 2-3 get created. So I figured i'd try here and see if any brightspark can narrow down my issue.
Updated removing windows load as per change to main website.

The simple answer is that you are setting the style to inline. An <option> tag should not be inline, or have any style like that. The inline style i causing the problems.
Instead add the <option> tags when you need them. Store all the values in a object to add/remove them.
By the way. Remove that window load thing.
Here is the javascript fix:
$(document).ready(function()
{
var options = $('#apick option');
var values = $.map(options, function(option)
{
return option;
});
$('.areaselect')
.on('click', function()
{
var apick = $('#apick').empty();
var id = $(this).attr('id');
var newValues = $.grep(values, function(n, i)
{
return $(n).hasClass(id);
});
apick.append(newValues).show().find('option:first').attr('selected','selected');
return false;
});
});

Related

Show div when click on a different div, and show a different div when clicked again

I currently have made a way so the user can add another text field to the form by pressing on a 'add_another' div, this uses basic JS so when the user presses on the div 'add_another' the div 'author_2' is toggled.
I would like to make it so that when the user presses on the 'add_another' div for a second time it shows 'author_3' div, and when they press 'add_another' again, it then shows 'author_4'. I have put all the CSS and HTML divs in place to support this, I am just trying to adapt my code so it shows one div after another, rather then toggling a single div.
Here is my JS:
<script>
$(document).ready(function() {
$('.add_another').on('click', function(){
$('.author_2').toggle();
});
});
</script>
I have tried altering this code, however with no luck.
I haven't added my HTML as it is just 4 divs, 'author_1' 'author_2' ... 3...4
Thankyou for your help
There are two solutions to Your problem.
First one - use static code
It means the max author count is 4 and if user gets to 4, this is it.
If so - You need to store the number of authors already shown.
var authors_shown = 1;
$(document).ready(function() {
$('.add_another').on('click', function(){
authors_shown++;
if (!$('.author_'+authors_shown).is(":visible")) {
$('.author_'+authors_shown).toggle();
}
});
});
But there is also a second - more dynamic option.
What if user wants to input 10 or 20 authors? You don't want to pre render all that html code and hide it. You should clone the div and change its id or if the (HTML) code (for another author) is not too long, you can render it within JS code.
var div = document.getElementById('div_id'),
clone = div.cloneNode(true); // true means clone all childNodes and all event handlers
clone.id = "some_id";
document.body.appendChild(clone);
If it's a form, then change names of input fields to array as author_firstname[]
Also You can store number of added authors in another hidden field (so you know how long to loop the form fields on the server side.
The second option is a bit more complex and longer, but way more dynamic.
You should make another div when clicked on add_another:
something like this:
<script>
$(document).ready(function() {
$('.add_another').on('click', function(){
$('<div><input type="text" name="name[]" /></div>').appendTo('.your_container');
});
});
</script>
as you see, input's name has [] which means you should treat with the inputs as an array.
let me know if you got any further questions
good luck.

Jquery is resetting after dynamic changes

I have a chartist.js bar graph. I want to customize x-axis labels. I wrote some following jquery for flipping first and last name and then add '...' at the end if the length of the text is more than 11 characters.
$(function () {
$('#AssignedLineChart .ct-labels, #ResolvedBarChart .ct-labels').find('.ct-label.ct-horizontal').each(function () {
var label = $(this).text();
var splitLabel = label.split(",");
var newLabel = splitLabel[1] + ", "+splitLabel[0];
if (newLabel.length > 13) {
newLabel = newLabel.substring(0, 10) + "...";
}
$(this).text(newLabel);
});
});
It applied fine when I load the page first time. There are some select options on bar charts for displaying individual ranges. When I select them the labels go back to their previous state. Selecting options are changing DOM. This also happens when I open inspect element tab.
Is there a way to use find or each method on dynamically changed elements?
$(function () {
This is only applied when the page finishes loading and get fired 1 time only.
Selecting options are changing DOM.
So the current process is like:
Page finishes loading.
The label got changed by document ready event. (*)
The label got changed by other events, this case, the select options. (**)
So, it changed the DOM dynamically and nothing like above (*) changes the label again.
So, to change the label after select options, you need to change it in the callback function of what is done after select options in the above mentioned (**).

Create a function to hide divs

I want to display tables when a selection is made in a form and a 'Generate Factsheet' button is clicked. I've got a working code where I individually hide other divs when displaying the one I am interested in. Since I have several options in the form (and hence several corresponding divs in which the respective tables are enclosed), the final code appears bulky. I want to write a function to hide other divs whiles displaying the one I am interested in. This is the code I currently have:
var tableDivs = ['tableOPVDiv','tablePneumoDiv','tableRotaDiv'];
var selectedVaccine;
var selectedTableDiv;
function generateFactsheetFunction(){
// Selecting the vaccine chosen from the dropdown
var e = document.getElementById("selectVaccine");
selectedVaccine = e.options[e.selectedIndex].text;
console.log("selectedVaccine: ", selectedVaccine);
if (selectedVaccine=="Rotavirus Vaccine"){
selectedTableDiv='tableRotaDiv';
console.log("rotavirus selected");
hideOtherTables();
} else if (selectedVaccine=="Polio Vaccine"){
console.log("polio selected");
selectedTableDiv='tableOPVDiv';
hideOtherTables();
} else if (selectedVaccine=="Pneumococcal Vaccine"){
console.log("pneumo selected");
selectedTableDiv='tablePneumoDiv';
hideOtherTables();
}
}
function hideOtherTables(){
var testa = tableDivs.indexOf(selectedTableDiv);
console.log("tableDivs[testa]: ", tableDivs[testa]);
console.log("testa: ", testa);
testb = tableDivs[testa];
console.log("testb: ", testb);
document.getElementById(tableDivs[testa]).style.display="block";
/*var newTableDivs=tableDivs.splice(testa);*/
/*for (y=0;y<newTableDivs.length;y++){
document.getElementById(newTableDivs[y]).style.display="none";
}*/
}
The uncommented part works fine. In the commented part, I want to say that for all array elements other than selectedVaccine, I want the display to be:
document.getElementById(tableDivs[testa]).style.display="none";
I cannot splice the data because the selections are repititive (the selections are from a form). What is the way to set the visibility of tableDivs associated with other selections to be none.
Why should you change the display property of each and every division seperately? give a common class name to all the divisions and hide them all at once and then display only the required table.
$(".yourClass").hide();
document.getElementById(tableDivs[testa]).style.display="block";
You will have to use the jQuery Library too.
If you are not familiar with jQuery then use the for loop to hide all the tables first and then display only the required table.
for (y=0;y<TableDivs.length;y++){//you need not create newTableDivs
document.getElementById(TableDivs[y]).style.display="none";
}
document.getElementById(tableDivs[testa]).style.display="block";
i.e you just have to interchange the order of execution. ;)
Cannot read property 'style' of null this means that document.getElementById(tableDivs[y]) return null and can not find this element
try to write
document.getElementById("ElementId")

jQuery setting prop("selected", true) on multi select list in Chrome only works once

When trying to set a select list option to selected in order to scroll the select list to that option, it works in all browsers except for Chrome. In Chrome it works once, but successive times do not work in Chrome. How can I ensure that setting the selected attribute of an option in a select list will scroll that option into view?
Here is an example of my issue - http://jsfiddle.net/Z2rQG/
The code I am using to select an option in a list to scroll it into to view is as follows:
(function ($) {
$.fn.scrollToOption = function (option) {
var _option = $(option, this);
// if option is in list
if(_option) {
// store the selection state
var isSelected = _option.is(":selected");
_option.prop("selected", true); // scroll to the option
_option.prop("selected", isSelected); // restore the selection state
}
return this;
};
})(jQuery);
Edit: I have also tried the scrollTo jQuery plugin, which does not work as well in Chrome. Here is an example - http://jsfiddle.net/kavun/TW4XK/
Edit: Here is a clearer example of what I am trying to do. Select two options from a select list and have the list be scrolled to the last selected option. This works in all browsers except Chrome and Safari. In Chrome the first selection scrolls to the option but the second $('#select option[value=""].prop('selected', true); does not scroll the list - http://jsfiddle.net/kavun/uhnZH/
Browser behaviour is inconsistent with regard to which option is scrolled into view when multiple options are selected. However, selecting the option using its selected property plus setting the selectedIndex property of the <select> element seems to make sure the select is scrolled to the right place in all major browsers. Using this, you can get the correct vertical scrolling, select the options you want and then scroll the select manually.
Opera does not seem to fully support scrollTop for select elements, so this solution does not work in Opera.
Demo: http://jsfiddle.net/uhnZH/10/
Code:
function selectAndScrollToOption(select, option) {
$select = $(select);
// Store the currently selected options
var $selectedOptions = $select.find("option:selected");
// Select the new option using its selected property and selectedIndex.
// This seems to make the select scroll to the desired place in all major
// browsers
option.selected = true; // Required for old IE
select.selectedIndex = option.index;
// Measure the vertical scrolling
var scrollTop = $select.scrollTop();
// Re-select the original options
$selectedOptions.prop("selected", true);
// Scroll to the correct place
$select.scrollTop(scrollTop);
}
If your goal is simply to scroll to a value in the dropdown, you can simply use val as demonstrated in this updated fiddle:
$('#selectList').val(51);
That will work in any browser.
If you're trying to scroll to an element on the page based on the value in the dropdown, you'll have to put up an example that gets us a bit closer to what you want so we can address that specific scenario.

How do you scroll a select box to a specific point (using javascript or jQuery)?

I want to make the selected option appear in the middle of a drop-down. When I first load the page it appears at the bottom of the drop-down, but if I scroll past it and exit it remembers that when I open it again. I want it to make it appear in the middle by default.
At first I thought I could just use javascript to select an option past the one I want, then set it back to the correct option. I've played with scrollTop and scrollTo, but none of them seem to give me what I need. I've been testing it in Chrome, but it also needs to work in Firefox and IE. Any ideas?
Edit: I tried the scrollTo plugin but it doesn't seem to work for drop-downs. Take a look at these code snippets
From HTML:
<select id="test">
<option>1</option>
<option>2</option>
// ........
<option selected="selected">21</option>
<option>22</option>
// ........
<option>40</option>
</select>
From Javascript:
$(function() {
alert( $('#test option:selected').next().text() ); // alerts 22
$().scrollTo('#test'); // scrolls the screen to the drop-down
$('#test').scrollTo( $('#test option:selected').next() ); //does nothing
});
Use this jQuery plugin: http://plugins.jquery.com/project/ScrollTo
Documentation
Demo 1 or Demo 2
Edit -
Final Solution:
Because a drop-down list is brower-handled and can't be manipulated very well, you have to recreate the behavior of a drop-down list yourself. Look at the comments for more information.
What worked for me (in Chrome and Firefox):
<select onclick="centerSelectedOption(this)">
...
</select>
<script type="text/javascript">
function centerSelectedOption(selectBox) {
var selectedIndex = selectBox.selectedIndex;
var optionCount = selectBox.options.length
/* browser shows 20 options at a time (as long as list is long enough)
hence a center position of 10 would be fine
we can achieve this by briefly selecting the (selectedIndex+10)th option
and then back to the actual selectedIndex */
if (optionCount > 20) {
var upperIndex = Math.min(optionCount, selectedIndex + 10);
selectBox.selectedIndex = upperIndex; // hereby the browser scrolls the options list so that upperIndex is at the end
// if the options list was already scrolled down and an option higher up is selected, we have to scroll up again
var lowerIndex = Math.max(0, selectedIndex - 9);
selectBox.selectedIndex = lowerIndex; // hereby the browser scrolls the options list so that lowerIndex is at the top
// finally go back to the actually selected option
selectBox.selectedIndex = selectedIndex;
}
}
</script>
$(".MyDDL").val('2');
[jQuery.val] checks, or selects, all
the radio buttons, checkboxes, and
select options that match the set of
values.
I ran into this problem... my solution doesn't really use jquery (although the page itself does...) I thought this was more appropriate for what I was doing; and easier to implement than jquery. The problem I was having was properly making an HTML form update after javascript was used to get _GET params to pass off to ajax ... after the user hit 'submit' they would lose all of their selections.
function getURLParameter(param_name) {
// get the _get parameter
var check = decodeURI((RegExp(param_name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]);
// get the form in the document (by id/name)
if(typeof document.myForm[param_name] !== 'undefined'){
var form_param = document.myForm[param_name];
for(key2 in form_param.options)
if(form_param.options[key2].value == check){
// change index
form_param.selectedIndex = form_param.options[key2].index;
return check;
}
}
// Return a 'null' string value if get param isn't there
return check;
}

Categories

Resources