Drop down menu selection ditactes what form will display - javascript

I'm currently working on a project that saves details of different types of objects to a database e.g. book, webpage and journal article. To save the different attributes of these objects I am trying to get different forms to display that depend on the selection in a drop down menu.
Here's the dropdown menu:
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown">
Select Reference Type...
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
<li role="presentation"><a role="menuitem" tabindex="-1" href="book.php">Book</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="journal.php">Journal</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="webpage.php">Webpage</a></li>
</ul>
</div>
How to I get a different form to load on screen without redirecting to a different page. I've been trying to do this in php but I get the feeling that php isn't the right way of going about doing this. Also, apologies in advance as I have no previous experience in Javascript, AJAX or jQuery.

Okay, so without knowing the rest of your code, I would suggest that the best option would be to have the different forms in separate documents.
For example
HTML
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown">
Select Reference Type...
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
<li role="presentation"><a onclick="bookinclude()" role="menuitem" tabindex="-1" href="book.php">Book</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="journal.php">Journal</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="webpage.php">Webpage</a></li>
</ul>
</div>
<div id="contentwrapper">
Some Initial Content Here
</div>
Javascript
function bookinclude(){
$("#contentwrapper").fadeOut(400);
setTimeout(function(){$("#contentwrapper").load("book.php").fadeIn();}, 400);
};
And remember to include Jquery!In the head of your HTML:
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Basically, on the click of the book link, it will load the book.php into the contentwrapper div.
I think this is what you want? All you need to do is replicate the function, and the link, but replace the book with journal, and with webpage.
Hope this helps!

you can also keep all the 3 forms on the same page and can hide or show them on the basis of the dropdown selection.
Lets say there are 3 forms:
1. book
2. webpage
3. journal
Create forms for all three in html, and by default keep all of them hidden(for that we will use a class "display-none"), after that detect change in the dropdown on basis of whom the form populates and do action as required. Please look at the following peace of code, it might help:
<style type="text/css">
.display-none {
display: none;
}
</style>
<select id="dropdown" onchange="myFunction()">
<option value="-1">-- Select --</option>
<option value="book">Book</option>
<option value="webpage">Webpage</option>
<option value="journal">Journal</option>
</select>
<form id="book" class="display-none" method="post" action="where-you-want-to-post/book">
<input type="submit" value="Submit Book" />
</form>
<form id="webpage" class="display-none" method="post" action="where-you-want-to-post/webpage">
<input type="submit" value="Submit Webpage" />
</form>
<form id="journal" class="display-none" method="post" action="where-you-want-to-post/journal">
<input type="submit" value="Submit Journal" />
</form>
<script type="text/javascript">
function myFunction() {
var allForms = document.getElementsByTagName('form');
var dropdown = document.getElementById("dropdown");
if (dropdown.value != "-1") {
var form = document.getElementById(dropdown.value);
for (var i = 0; i < allForms.length; i++) {
allForms[i].setAttribute("class", "display-none");
}
form.setAttribute("class", "");
}
}
</script>
Demo: http://jsfiddle.net/oynjj3jn/

In order to accomplish your goal, you would need the following
A menu in your HTML page like this one. Let's say that the values of the select-list will be your PHP files, just as it's shown below
<!-- HTML -->
<p>Select reference type...</p>
<!-- This is the menu -->
<select id="menu">
<option value="book.php">Book</option>
<option value="jurnal.php">Jurnal</option>
<option value="webpage.php">Webpage</option>
</select>
<!-- This is the container for your HTML content -->
<div id="content"></div>
You'll need this snippet to make AJAX requests to your server
// JavaScript
var s = document.getElementById('menu'); // reference to the <select> menu
var c = document.getElementById('content'); // reference to the content <div>
s.onchange = function(){ // hook the change event on <select>
xhr = new XMLHttpRequest();
var url = 'your-domain/' + this.value; // here we're passing the selected value
xhr.open("GET", url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) { // wait for the response
c.innerHTML = xhr.responseText; // here it comes; populate the <div>
}
};
xhr.send();
};
And these are your PHP files on the server-side; they may contain any valid PHP / HTML code
// PHP
// book.php or jurnal.php or webpage.php
echo 'anything';

Related

How do I add dropdown menu to JavaScript template literal

I am trying to add a feature whereby when the user clicks on another user's name a dropdown menu appears with some options. The username is dynamically created using AJAX and template literals. The drop down menu appears to append when I check in dev tools but it doesn't physically appear in the UI. I'm not sure if I am going about it in the right manner. Here is my code:
`
[...]
<div class=card-text">
<p class="venue-text">${venueDescription}</p>
<h6 class="venue-source card-subtitle" id="${source}-adder" data-idtext="${source}-adder">-${source}</h6>
</div>
<div id="o"></div>
</div>
</div>
`);
venueCard.appendTo(myCol);
myCol.appendTo('#venueCard');
document.getElementById(source + "-adder").addEventListener('click', function(e) {
if (e.target && e.target.matches("h6.venue-source")) {
let sourceDropdown = document.getElementById('o');
let dropdown = $(`
<div class="dropdown">
<div class="user-options" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></div>
<div id="${source}-dropdown" class="venue-card-dropdown dropdown-menu" aria-labelledby="dropdownMenuButton">
<a id="share ${source}" data-idtext="share-${source}" class="dropdown-item" href="#">Share</a>
<a id="add ${source}" data-idtext="${source}" class="dropdown-item add" href="#">Add to List</a>
</div>
</div>
`)
console.log(`dropdown for ${source}`)
dropdown.appendTo(sourceDropdown)
};
});

Vue select style functionality on a boostrap dropdown

I've just started using Vue, (which seems really nice) and I've run into an issue.
I have a bootstrap4 dropdown that I'm using to populate a hidden form (clicking on a dropdown-item saves the data value to the form below).
This is only done as I can't style the normal select/option dropdown as I would like.
This was all working fine, until I tried implementing vue, as I'm not using a select component directly the solutions offered in the vue select documentation don't seem to work.
Any help would be much appreciated.
Thanks in advance
html
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle device-dropdown" type="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
All Devices
</button>
<div class="dropdown-menu" aria-labelledby="device-dropdown">
<a class="dropdown-item" href="#" data-value="all">All Devices</a>
<a class="dropdown-item" href="#" data-value="imac">iMac</a>
<a class="dropdown-item" href="#" data-value="macbook">MacBook</a>
<a class="dropdown-item" href="#" data-value="ipad">iPad</a>
<a class="dropdown-item" href="#" data-value="iphone">iPhone</a>
</div>
<select name="device" class="hidden-device-dropdown">
<option></option>
</select>
</div>
js
// copies the selected dropdown element into a hidden select in the form
$('.dropdown-menu').click(function (e) {
e.preventDefault();
// change button text to selected item
var selected = $(e.target);
$(".device-dropdown").text($(selected).text());
// change option value (inside select) to selected dropdown
var form = $("select.hidden-device-dropdown").children("option");
$(form).val(selected.data("value"));
});
Edit: looks like v-on:click="device = '...'" might get me the functionality I'm after, is this a good way of doing it? seems to be duplicating a lot of code
I would suggest a component.
Vue.component("bs-dropdown",{
props:["options", "value"],
template:`
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle"
:class="id"
ref="dropdown"
type="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
{{selected.text}}
</button>
<div class="dropdown-menu" :aria-labelledby="id">
<a class="dropdown-item"
href="#"
v-for="option in options"
#click="selected = option">
{{option.text}}
</a>
</div>
</div>
`,
computed:{
selected:{
get() {return this.value},
set(v){this.$emit("input", v)}
},
id(){
return `dropdown-${this._uid}`
}
},
mounted(){
$(this.$refs.dropdown).dropdown()
}
})
This component wraps the bootstrap functionality, which is what you typically want to do when integrating with external libraries.
Use it like so:
<bs-dropdown :options="devices" v-model="selected"></bs-dropdown>
Here is a codepen demonstrating it in action.
If/when you need the value, instead of copying it to a hidden select, the value is a data property bound with v-model. You can use that however you like.

Convert razor enumdropdownlistfor to bootstrap button group dropdown

I have a razor syntax enumdropdownlist for displaying either active/inactive status.
#Html.EnumDropDownListFor(model => model.Status, new { #class = "btn btn-default btn-lg dropdown-toggle" })
I want to use a button group drop down with glyphs like I have below but don't know how to get my model value 'model.Status' to set the value of the button group drop down.
$(document).ready(function() {
$('#item1').on('click', function() {
$('#item0').text('Active');
});
$('#item2').on('click', function() {
$('#item0').text('Not Listed');
});
});
<div class="btn-group">
<button id="item0" type="button" class="btn btn-default">Action</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li id="item1">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>Active
</li>
<li id="item2">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>Not Listed
</li>
</ul>
</div>
I don't care if I use html or razor, I just want to use the boostrap button drop down with glyphs and I want to be able to set the enumerated view model value active/inactive (Status) when the page loads.
Although the Bootstrap dropdown buttons look similar to a select list, their functionality is vastly different. I wouldn't recommend trying to use a Bootstrap dropdown button as a replacement for a select list if you need to actually post the "selected" item.
If you're just looking for a more stylistic and visually appealing alternative to a traditional select control, take a look at something like Select2, and while the look is pleasant enough out of the box, there's also a project that styles it to fit even better with the rest of Bootstrap.
If you're dead set on using Bootstrap dropdown buttons, you've got a lot of work ahead of you. You'll need to set up some JavaScript that will read the information from the select element and dynamically create the Boostrap dropdown button based on that, while hiding the original select. Then, you'll need to map over all the events such as a click on one of the items in the dropdown so that it selects the same item in the actual select element. You'll also have to account for highlighting the item in the dropdown that corresponds with the selected option in the select list, etc. If you run into specific problems while writing all that code, you can ask additional questions here as necessary, but providing you with all the code you'll need here is far beyond the scope of StackOverflow.
You can try to enumerate through enum values and put them in page, please notice the Html.HiddenFor from the end, we will use it to store the selected Status.
<div class="btn-group">
<button id="item0" type="button" class="btn btn-default">Action</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
#{
var values = Enum.GetValues(typeof(Status));
for(int i=0; i < values.Count; i++)
{
var status = (Status)values[i];
<li id="item#(i+1)" class="select-status" data-status="#values[i]">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>#status.ToString()
</li>
}
}
</ul>
</div>
#Html.HiddenFor(model => model.Status)
After we create the html we have to update the selected Status in Html.HiddenFor to persist when a POST is performed.
$(document).ready(function() {
$('.select-status').click(function(){
$('#Status').val($(this).data('status')); // update the status in hidden input
});
#for(int i=0; i < values.Count; i++)
{
<text>
$('#item#(i+1)').on('click', function() {
$('#item0').text('#status.ToString()');
});
</text>
}
});
HTML snippet example:
$(document).ready(function() {
$('.select-status').click(function(){
$('#Status').val($(this).data('status')); // update the status in hidden input
});
$('#item1').on('click', function() {
$('#item0').text('Active');
});
$('#item2').on('click', function() {
$('#item0').text('Not Listed');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<div class="btn-group">
<button id="item0" type="button" class="btn btn-default">Action</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li id="item1" class="select-status" data-status="1">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>Active
</li>
<li id="item2" class="select-status" data-status="2">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>Not Listed
</li>
</ul>
</div>
<br />
Visible Status just for test
<input type="text" id="Status" value="1" />
Note: The code may have some errors but the logic/flow is the same.
In .cshtml file
<script>
myModelStatus = '#Model.Status';
</script>
#Html.EnumDropDownListFor(model => model.Status, new { #class = "btn btn-default btn-lg dropdown-toggle" })
more html here...
In your js file
$(document).ready(function() {
var status = myModelStatus;
$('#item1').on('click', function() {
$('#item0').text('Active');
});
$('#item2').on('click', function() {
$('#item0').text('Not Listed');
});
});
You are listening for click events on the li element rather than on the anchor tag
You should stop event propagation by using event.preventDefault() method.

Only show country subset text in bootstrap formhelpers country picker

I am using Bootstrap FormHelpers country picker and I have the following init code:
<div class="bfh-selectbox bfh-languages pull-right" data-language="es_ES" data-available="gl_ES,ca_ES,eu_ES,es_ES" data-flags="false" data-blank="false"></div>
This code generate this output:
<div class="bfh-selectbox bfh-languages pull-right" data-language="es_es" data-available="gl_ES,ca_ES,eu_ES,es_ES" data-flags="false" data-blank="false">
<input type="hidden" name="" value="es_es">
<a class="bfh-selectbox-toggle form-control" role="button" data-toggle="bfh-selectbox" href="#">
<span class="bfh-selectbox-option">Galego (Spain)</span>
<span class="caret selectbox-caret"></span></a>
<div class="bfh-selectbox-options">
<div role="listbox">
<ul role="option">
<li>
<a tabindex="-1" href="#" data-option="gl_ES">Galego (Spain)</a>
</li>
<li><a tabindex="-1" href="#" data-option="ca_ES">Català (Spain)</a></li>
<li><a tabindex="-1" href="#" data-option="eu_ES">Euskara (Spain)</a></li>
<li><a tabindex="-1" href="#" data-option="es_ES">Español (Spain)</a></li>
</ul>
</div>
</div>
That's is fine, but I would get only the subset names like "Galego", "Catalá", "Euskara", and "Español", but avoiding the append of " (Spain)" (country name). So the bootstrap select only will show the subset locale country names.
Could be this implemented easily? The only thing that I think that could work and it is very ugly is access to the DOM and remove in each li role="option" the " (Spain)" text after load the page, but I am looking for some elegant way maybe initializing bootstrap options.
It's simple if you declare it with: data-language="es" instead of es_ES
<div class="bfh-selectbox bfh-languages pull-right" data-language="es" data-available="gl_ES,ca_ES,eu_ES,es_ES" data-flags="false" data-blank="false"></div>
This is the documentation for Language Picker
This is the only tricky way that I figure out using javascript, since I think that bootstrap component doesn't allow this feature with native implementation. Writing here the solution if helps in future to someone more:
<script>
$( document ).ready(function()
{
$('.bfh-selectbox-options li a').each(function(key, value) {
//console.log($(this).text().replace(' (Spain)',''))
$(this).text($(this).text().replace(' (Spain)',''))
});
$('.bfh-selectbox-option').text($('.bfh-selectbox-option').text().replace(' (Spain)',''))
});
</script>

How to update a textfield based on other form elements

I'm writing a little database query app.
What i'm trying to do: Each time a checkbox is clicked, i'd like for a query that includes the selected fields to be generated and inserted into the textarea.
The problem: For some reason, with every click, its showing the query from the previous click event, not the current one.
Here's the markup:
<div class="application container" ng-controller="OQB_Controller">
<!-- top headr -->
<nav class="navbar navbar-default navbar-fixed-top navbar-inverse shadow" role="navigation">
<a class="navbar-brand">
Algebraix Database Client
</a>
<ul class="nav navbar-nav navbar-right">
<!--<li>Clear Queries</li>-->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-import"></span> Load Data <b class="caret"></b></a>
<ul class="dropdown-menu">
<li>Default Data</li>
<li>Custom Import</li>
<!-- <li class="divider"></li> -->
</ul>
</li>
<li>
<a href="" class="queries-clear">
<span class="glyphicon glyphicon-remove"></span> Clear Queries
</a>
</li>
</ul>
</nav>
<!-- left column -->
<div class="col-md-4">
<div class="well form-group">
<ul>
<li ng-repeat="option in options">
<input type="checkbox" class="included-{{option.included}}" value="{{option.value}}" ng-click="buildQuery()" ng-model="option.included"> {{option.text}}
</li>
</ul>
</div>
</div>
<!-- right column -->
<div class="col-md-8">
<form role="form" id="sparqlForm" method="POST" action="" class="form howblock">
<div class="form-group">
<!--<label>Query</label>-->
<textarea type="text" name="query" class="form-control" rows="10" placeholder="Write your SPARQL query here">{{query}}</textarea>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Submit Query" data-loading-text="Running Query..." />
</div>
</form>
</div>
</div>
And in my controller, i am doing the following:
var OQB_Controller = function($scope) {
console.log('OQB_CONTROLLER');
$scope.query = 0;
$scope.options = [
{ text: "checkbox1", value: "xyz123", included: false }
,{ text: "checkbox2", value: "abcRRR", included: false }
,{ text: "checkbox2", value: "abcRRR", included: false }
];
$scope.buildQuery = function() {
console.log('click');
var lines = [];
lines.push("SELECT *");
lines.push("WHERE {");
lines.push(" ?s ?p ?o .");
for(var i = 0; i<$scope.options.length; i++) {
var line = $scope.options[i];
console.log( line.value, line.included, i );
if( line.included ) {
lines.push(" OPTIONAL { ?s "+line.value+" ?o } .");
}
}
lines.push("}");
lines.push("LIMIT 10");
var _query = lines.join("\n");
$scope.query = _query;
};
};
To reiterate, every time the build query method is called, the state of the included booleans is from one click event prior. this has the symptoms of the classic javascript problem of the keyup vs keydown and the state of the event... however, i'm not sure if that is what is happening here.
is there a better way to do build the query (than what i'm currently doing) and populate the textarea based on the checked boxes?
use ng-change instead of ng-click because it is more appropriate for this particular desired behavior. See the ng-change documentation below:
The ngChange expression is only evaluated when a change in the input
value causes a new value to be committed to the model.
It will not be evaluated:
if the value returned from the $parsers transformation pipeline has
not changed if the input has continued to be invalid since the model
will stay null if the model is changed programmatically and not by a
change to the input value

Categories

Resources