Select menu closes once you click on it - javascript

I create a <select> menu using Javascript then attach it to the page. But when I click on it, it closes immediately.
Here's my code, I'm stumpped.
var accounts = [
['user1', 'password'],
['user2', 'passowrd']
]
function html(){
var button = 'Switch User • ';
$('a[href=search.php]')[0].before(button);
$('#switchacc').click(function(){
$(this).html('<select id="accounts">'+ accountss +'</select>');
return false;
});
var accountss = '';
for(i = 0; i <= accounts.length; i++){
accountss = accountss + '<option name="' + accounts[i][0] + '" value="' + i + '">' + accounts[i][0] + '</option>';
}
}
html();

Why are you embedding your select in that a link? See this fiddle for an example. You cannot embed a list in a link.

Related

Razor JQuery Populate Drop Down from Model array

I am using a WebGrid to allow CRUD on my database (using MVC and EF entities). The grid works and filters they way I want it to. There are two columns that use dropdowns to display a value tied to another table (Projects and People) and these both work well for edits/ updates. I am using JQuery for an add new row and want the new row to have select fields like the grid does (so that the user can just find the person by name instead of having to enter the ID for example). I am referencing this post from another similar question, but when I implement the code I get a syntax error that I'm having trouble understanding.
Here is my scripting on the view side that shows my failed attempt. I'm creating an array from the project repository (Text is the name of the project and Value is the ID field), and populating it with the model values: Model.Projects, and then in the add row function I want to loop through the array to add in the options.
<script type="text/javascript">
var ProjectArray = new Array();
#foreach (var proj in Model.projects)
{
#:ProjectArray.push(Text: "#proj.Text", Value: "#proj.Value");
}
</script>
<script type="text/javascript">
$(function ()
{
$('body').on("click", ".add", function () {
var SelectedProject = "#Model.ProjectID";
var newRow = $('.save').length;
console.log('newRow = ' + newRow);
if (newRow == 0) {
var index = "new"+$("#meetingList tbody tr").length + 1;
var ProjectID = "ProjectID_" + index;
var Date = "Date_" + index;
var Attendees = "Attendees_" + index;
var Phase = "Phase_" + index;
var PeopleID = "PeopleID_" + index;
var Save = "Save _" + index;
var Cancel = "Cancel_" + index;
var tr = '<tr class="alternate-row"><td><span> <input id="' + ProjectID + '" type="select"/></span></td>' +
#* This is where I use the array to add the options to the select box*#
ProjectArray.forEach(function (item) {
if (item.Value == SelectedProject) { '<option selected="selected" value="' + item.Value + '">' + item.Text + '</option>' }
else { '<option value="' + item.Value + '">' + item.Text + '</option>' }
+
});
---remaining script omitted----
'<td><span> <input id="' + PeopleID + '" type="text" /></span></td>' +
'<td><span> <input id="' + Date + '" type="date" /></span></td>' +
'<td><span> <input id="' + Attendees + '" type="text" /></span></td>' +
'<td><span> <input id="' + Phase + '" type="text" /></span></td>' +
'<td> SaveCancel</td>' +
'</tr>';
console.log(tr);
$("#meetingList tbody").append(tr);
}
});
I am not sure how to parse the error, but the page source looks like this when creating my client side array:
var ProjectArray = new Array();
ProjectArray.push(Text: "Select Project", Value: ""); //<-- ERROR HERE:
ProjectArray.push(Text: "010111.00", Value: "74");
ProjectArray.push(Text: "013138.00", Value: "2");
So the model getting into the client side works (the text and value pairs are correct), but the error I get is for the first array.push line: missing ) after the argument list. I have played with moving this code block around, putting it in a separate <script> tag and the error likewise follows it around, always on the first array.push line. And regardless of where it is, the rest of my script functions no longer work. I think it must be something silly but I just am not seeing what I'm doing wrong.
The option list does not populate into something I can ever see, it just renders out on the page source as the javascript loop:
var tr = '<tr class="alternate-row"><td><span> <input id="' + ProjectID + '" type="select"/></span></td>' +
ProjectArray.forEach(function (item) {
if (item.Value == SelectedProject) { '<option selected="selected" value="' + item.Value + '">' + item.Text + '</option>' }
else { '<option value="' + item.Value + '">' + item.Text + '</option>' }
+
}); //-- Unexpected token here
And with the push array in its separate script block I get a second error that the last } is an unexpected token. This is some javascripting error I'm sure. But where it is an how to do this are beyond me right now.
I'm not used to javascript, and poor syntax leads to the vague errors I was getting. The first problem was fixed by adding the { . . . } around the array values. Then I created a function to create the arrays I need for people and projects as well as a function to take an array and create the option list to clean up the view code:
function createProjectArray() {
var ProjectArray = new Array();
#foreach (var proj in Model.projects)
{
if (proj.Value != "") {
#:ProjectArray.push({ Text: "#proj.Text", Value: "#proj.Value" });
}
}
return ProjectArray;
}
function createPeopleArray() {
var PeopleArray = new Array();
#foreach (var person in Model.people)
{
if (person.Value != "") {
#:PeopleArray.push({ Text: "#person.Text", Value: "#person.Value" });
}
}
return PeopleArray;
}
function SelectOptionsString(MyArray, SelectedValue) {
console.log(MyArray);
var OptionsList = "";
MyArray.forEach(item => {
if (item.Value == SelectedValue) { OptionsList += '<option
selected="selected" value="' + item.Value + '">' + item.Text + '</option>'; }
else { OptionsList += '<option value="' + item.Value + '">' + item.Text
+ '</option>'; }
})
return OptionsList;
}
Taking this approach allowed me to more easily parse the code and find the syntax errors. The Array.forEach syntax was an interesting hurdle, and this site helped me test out my syntax to eventually get it working as above.
So the server creates the javascript lines to create the array, and then I use the array to create my dropdown options list. This cleans up the add row function code nicely:
$('body').on("click",".addrow", function() {
var SelectedProject = "#Model.ProjectID";
var ProjectArray = createProjectArray();
var ProjectOptions = "";
ProjectOptions = SelectOptionsString(ProjectArray, SelectedProject);
var PeopleArray = createPeopleArray();
var PeopleOptions = "";
PeopleOptions = SelectOptionsString(PeopleArray, "");
var tr = '<tr class="alternate-row"><td><span> <select id="' +
ProjectID + '>' + ProjectOptions + '</select></span></td>' +
'<td><span> <select id="' + PeopleID + '>' + PeopleOptions +
'</select></span></td>' + '</tr>'
$("#myWebGrid tbody").append(tr);
});
And it also allows for some potential code reuse.

EventListener showing wrong target

I have the following JS code
var existingMenus = document.getElementsByClassName('multiSelectMenu');
for (var i = 0; i < existingMenus.length; i++) {
var existingMenu = existingMenus[i];
var existingMenuHTML = [];
var targetChildren = existingMenu.parentElement.nextElementSibling.children;
console.log(targetChildren)
// Here I'm adding +1 to the ID as it appears starting at zero with a styled checkbox does not work correctly
for (var x = 0; x < targetChildren.length; x++) {
if (targetChildren[x].selected) {
existingMenuHTML += '<li><input class="dropdown-input" type="checkbox" id="' + (x + 1) + '" data-label="' + targetChildren[x].textContent + '" checked="true"/><label class="multiLabel" for="' + (x +
1) + '"><span></span> ' + targetChildren[x].textContent + ' </label></li>';
} else {
existingMenuHTML += '<li><input class="dropdown-input" type="checkbox" id="' + (x + 1) + '" data-label="' + targetChildren[x].textContent + '"/><label class="multiLabel" for="' + (x + 1) +
'"><span></span> ' + targetChildren[x].textContent + ' </label></li>';
}
}
existingMenu.innerHTML += existingMenuHTML;
console.log(existingMenuHTML)
var inputs = existingMenu.children;
console.log(inputs);
for (var w = 0; w < inputs.length; w++) {
var input = inputs[w].children[0];
console.log(input);
input.addEventListener('click', function() {
console.log('--------------')
console.log(event)
var targetElement = event.target || event.srcElement;
console.log(targetElement);
var elementParent = targetElement.parentElement.parentElement.parentElement;
console.log(elementParent)
if (!elementParent.classList.contains('open')) {
elementParent.className += ' open';
}
var multiList = elementParent.nextSibling.querySelector('[value="' + targetElement.dataset.label + '"]');
console.log(multiList)
// Subtracting one to account for the plus one I added above
var inputId = targetElement.id - 1;
if (targetElement.checked == true) {
multiList.selected = "selcted";
} else {
multiList.selected = "";
}
console.log('--------------')
});
}
}
The code works correctly on the first instance of the multiPick but all others on page trigger the first multiSelectMenu items even though I was clicking on the 3rd multiSelectMenu on page.
Here is a screen shot of the console,
Here is a code pen, https://jsfiddle.net/6s3rc8d7/ When you click the 'label' and not the checkbox it has the same issue I am seeing.
The reason behind getting the different event.target in your fiddle is due to the below code snippet in your html.
<input class="dropdown-input" type="checkbox" id="1" data-label="English only">
<label class="multiLabel" for="1"><span></span> English only </label>
you can see that in the label element, you have the for attribute which contains the id of the input element. The functionality of for attribute is that the value of this identifies which form element a label is bound to. When you click on the label it will simulate the click event of the bounded element. This is why when you click the label , in your script the event.target is the input the label is bonded with.
More on for attribute you can read here. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label
I was able to rework the code and added the EventListener to the label instead of the checkbox.

How to find a file with javascript?

My app is looking into a folder and then show all folders and html file inside it in a dropdown menu, and display any html files inside an iframe. I have a file called "highlighted.html" which I don't want to show in the dropdown menu, but if it is in the current directory I do want to show it automatically in an iframe.
This is my code to show what is in folder:
First function create a dropdown box loading dynamically folders or files (with html extension).
In second function: if click on an existing subfolder, then open that folder and look inside for html file(s) to open it in a iframe
function rendSelects($currentSelectItem, strPath) {
var currentSelectLevel = (null === $currentSelectItem ? -1 : parseInt($currentSelectItem.attr('data-selector-level'))),
nextOneSelectorHtml =
'<select ' +
'class="dropdown selectpicker" ' +
'name="dd" ' +
'data-selector-level="' + (currentSelectLevel + 1) + '" ' +
'data-path="' + strPath + '" ' +
'onchange="onFsSelectChange(this)"' +
'><option text selected> -- select an option -- </option>';
$('div.selectors-container select.dropdown').each(function (i, el) {
if (parseInt(el.getAttribute('data-selector-level')) > currentSelectLevel) {
el.parentNode.removeChild(el);
$(el).selectpicker('destroy');
}
});
if (fsStructure[strPath].subfolders.length > 0) {
for (var i = 0; i < fsStructure[strPath].subfolders.length; i++) {
nextOneSelectorHtml +=
'<option ' +
'class="subfolder-option" ' +
'data-subfolder="' + fsStructure[strPath].subfolders[i] + '" >' + fsStructure[strPath].subfolders[i] +
'</option>';
}
}
if (fsStructure[strPath].subshtmls.length > 0) {
for (var i = 0; i < fsStructure[strPath].subshtmls.length; i++) {
nextOneSelectorHtml +=
'<option ' +
'class="html-page-option" ' +
'data-html-page-name="' + fsStructure[strPath].subshtmls[i] + '">' + fsStructure[strPath].subshtmls[i] +
'</option>';
}
}
nextOneSelectorHtml += '</select>';
$('div.selectors-container').append(nextOneSelectorHtml);
$('div.selectors-container').trigger('dropdownadded.mh');
}
function onFsSelectChange(el) {
var currentSelectorPath = el.getAttribute('data-path'),
selectedOption = el.options[el.selectedIndex];
if (selectedOption.classList.contains('subfolder-option')) {
loadFolderStructure(currentSelectorPath + '/' + selectedOption.getAttribute('data-subfolder'), $(el))
}
if (selectedOption.classList.contains('html-page-option')) {
playSwf(currentSelectorPath + '/' + selectedOption.getAttribute('data-html-page-name'));
}
}
I have provided a working demo at http://tdhtestserver.herobo.com/.
SOLVED
Well. If highlighted.html does exist in folder, no select constitution. Let's display an iFrame with src=highlighted.html IIUC. Am I OK ?
First function create a dropdown boxes where it load dynamically folders or files with html extension.
Ok, so let's check if highlighted.html is here.
function rendSelects($currentSelectItem, strPath) {
//here : (begin of change)
if(strPath.indexOf("hightlighted")>=0) {
$("#myiFrame").attr('src', /path/to/highlighted)
}
// enfd of change. The continue as :
var currentSelectLevel = (null === $currentSelectItem ? -1 : parseInt($currentSelectItem.attr('data-selector-level'))),
nextOneSelectorHtml =....
ACTUALLY, the matter is to choose between : 1. $(myframeid).attr(src...) AND 2. $('div.selectors-container').append(nextOneSelectorHtml); /// you have to "render" 1 or 2, depending on finding highlighted in or not.
function rendSelects($currentSelectItem, strPath) {
//1of3 // let's add a boolean
var is_highlighted_here = false;
var highlighted_path="";
//done.
var currentSelectLevel = (null === $currentSelectItem ? -1 : parseInt($currentSelectItem.attr('data-selector-level'))),
nextOneSelectorHtml =
'<select ' +
'class="dropdown selectpicker" ' +
'name="dd" ' +
'data-selector-level="' + (currentSelectLevel + 1) + '" ' +
'data-path="' + strPath + '" ' +
'onchange="onFsSelectChange(this)"' +
'><option text selected> -- select an option -- </option>';
$('div.selectors-container select.dropdown').each(function (i, el) {
if (parseInt(el.getAttribute('data-selector-level')) > currentSelectLevel) {
el.parentNode.removeChild(el);
$(el).selectpicker('destroy');
}
});
if (fsStructure[strPath].subfolders.length > 0) {
for (var i = 0; i < fsStructure[strPath].subfolders.length; i++) {
nextOneSelectorHtml +=
'<option ' +
'class="subfolder-option" ' +
'data-subfolder="' + fsStructure[strPath].subfolders[i] + '" >' + fsStructure[strPath].subfolders[i] +
'</option>';
}
}
if (fsStructure[strPath].subshtmls.length > 0) {
for (var i = 0; i < fsStructure[strPath].subshtmls.length; i++) {
// 2of3 // oh !! look at here :
if( fsStructure[strPath].subshtmls[i].indexOf("highlighted")>=0 )
{
s_highlighted_here=true;
highlighted_path = fsStructure[strPath].subshtmls[i];
}
//done. scroll to bottom.
nextOneSelectorHtml +=
'<option ' +
'class="html-page-option" ' +
'data-html-page-name="' + fsStructure[strPath].subshtmls[i] + '">' + fsStructure[strPath].subshtmls[i] +
'</option>';
}
}
nextOneSelectorHtml += '</select>';
// 3of3 // here finally
if(is_highlighted_here) {
$("#myiFrame").attr('src', highlighted_path);
}
else {
$('div.selectors-container').append(nextOneSelectorHtml);
$('div.selectors-container').trigger('dropdownadded.mh');
}
}//function end
Well, if i display only changed :
- at the very function start :
//1of3
var is_highlighted_here = false;
var highlighted_path="";
when parsing the folder struct :
// 2of3 // oh !! look at here :
if( fsStructure[strPath].subshtmls[i].indexOf("highlighted")>=0 )
{
s_highlighted_here=true;
highlighted_path = fsStructure[strPath].subshtmls[i];
}
And finally, when rendering :
// 3of3
if(is_highlighted_here) {
$("#myiFrame").attr('src', highlighted_path);
}
else {
$('div.selectors-container').append(nextOneSelectorHtml);
$('div.selectors-container').trigger('dropdownadded.mh');
}
I answer on my question because some of you haven't understood my issue or they don't know how to do it. So I found that was so easy and all i've done was only one line of code.
high( currentSelectorPath + '/'+selectedOption.getAttribute('data-subfolder')+'/highlighted.html');
This line was changed everything, where high is a new iframe
function onFsSelectChange( el ) {
var
currentSelectorPath = el.getAttribute('data-path'),
selectedOption = el.options[el.selectedIndex];
if ( selectedOption.classList.contains('subfolder-option') ) {
loadFolderStructure( currentSelectorPath + '/' + selectedOption.getAttribute('data-subfolder'), $(el) )
high( currentSelectorPath + '/'+selectedOption.getAttribute('data-subfolder')+'/highlighted.html');
}
if ( selectedOption.classList.contains('html-page-option') ) {
playSwf( currentSelectorPath + '/' + selectedOption.getAttribute('data-html-page-name') );
}
}

how to get Id of row when pop up option click (got Id using global variable)?

can you please tell me how to get Id of row when pop up option click ?I generated the row dynamically when "add" button is press.on Row there is an icon ":" ,on click of icon it show pop up screen When I click "edit" or other option I want to show Id of row on which it it open .I am able to get event of edit .But not able to get id.
http://jsfiddle.net/4ajeB/5/
function createTestCase(testCaseName, iscreatedFromScript, jsonObject) {
var id;
if (typeof ($("#testCaseContainer li:last").attr('id')) == 'undefined') {
id = "tc_1";
var index = id.indexOf("_");
var count = id.substring(index + 1, id.length);
count = parseInt(count);
var conunter = count;
} else {
id = $("#testCaseContainer li:last").attr('id');
var index = id.indexOf("_");
var count = id.substring(index + 1, id.length);
count = parseInt(count);
var conunter = count;
id = id.substring(0, index) + "_" + parseInt(count + 1);
}
var html = '<div class="testcaselist_row">' + '<ul>' + '<li id="' + id + '" class="clickTestCaseRow">' + id + '<i class="icon1 test_h"></i></li>' + '</ul></div>';
$('#testCaseContainer').append(html).enhanceWithin();
}
$('.edit_h').click(function(){
alert("edit"+$(this).id)
})
I got the ID using global variable.Can it is possible to get ID without using variable ?
Just add the ID to the .edit_h as data, and access it in the click event.
...
$('.edit_h').data('originalId', id);
$('#testCaseContainer').append(html).enhanceWithin();
}
$('.edit_h').click(function(){
alert("edit ID:"+$(this).data('originalId'));
})
Updated fiddle: http://jsfiddle.net/4ajeB/6/

Make List Items Clickable in JavaScript

I am developing an Android app using Phonegap. In this app I have integrated Facebook login module. After user gets login into app, he/she can see friend list of his/her. I have done till this. What I have to do is, on clicking the particular friend name, that friend name should be added to another list. But my problem is this friend list is not clickable. How to make dynamic list clickable?Below is my code. What am I missing?
xyz.html
<div class="section">
<h1>Get user's friends</h1>
<div id="user-friends"></div>
<div class="button button-requires-connect" onclick="getUserFriends();hideButton(this);" />Get your friends</div>
<div class="info-requires-connect">You need to login before you can use this functionality.</div>
</div>
pqr.js
function getUserFriends() {
var markup = '<div class="data-header">Friends</div>';
for (var i=0; i < friendsInfo.length && i < 25; i++) {
var profilePictureUrl = '';
if (friendsInfo[i].picture.data) {
profilePictureUrl = friendsInfo[i].picture.data.url;
} else {
profilePictureUrl = friendsInfo[i].picture;
}
markup = markup + '<img src="' + profilePictureUrl + '">' + friendsInfo[i].name + '<br />';
}
document.getElementById('user-friends').innerHTML = markup;
}
You can wrap your 'friend-markup' for example in <li>s like that:
markup = markup + '<li><img src="' + profilePictureUrl + '">' + friendsInfo[i].name + '</li>'
and then use jQuery to bind clicks to the <li>s:
$('#user-friends').on('click', 'li', function() {
... do something
});
function getUserFriends() {
var markup = '<div class="data-header">Friends</div>';
for (var i=0; i < friendsInfo.length && i < 25; i++) {
var profilePictureUrl = '';
if (friendsInfo[i].picture.data) {
profilePictureUrl = friendsInfo[i].picture.data.url;
} else {
profilePictureUrl = friendsInfo[i].picture;
}
var clickableName = '<a href="" onclick="handleClick(this); return false;">'
+ friendsInfo[i].name + '</a>';
markup = markup + '<img src="' + profilePictureUrl + '">' + clickableName + '<br />';
}
document.getElementById('user-friends').innerHTML = markup;
}
Then write handler function
function handleClick(element/*which friend was clicked*/)
{
//do something with your friend
}
Or you can use jQuery to bind click event on element as #MiRaIT told

Categories

Resources