Choices-js keep option in select - javascript

I am using Choices.js to create a multi select option menu.
In the <select> menu it is required to be able to select the same <option> multiple times.
This issue has been resolved by using the addEventListener function from Choices.js.
The Issue
When i want to load the selected options from a string or ajax call the <option> are only selected one time instead of multiple times.
For example: the values 1 - 1 - 2 - 3 - 3 will need to display in the <select> menu ONE - ONE - TWO - THREE - THREE.
But for now i only displays ONE - TWO - THREE.
The issue is that the addEventListener is not working when the setChoiceByValue is being used.
document.addEventListener("DOMContentLoaded", function() {
const query_task = new Choices(document.querySelector('#query_task'), {
removeItemButton: true,
maxItemCount: 10,
});
query_task.passedElement.element.addEventListener('addItem', function(e) {
query_task.setChoices([{
value: e.detail.value,
label: e.detail.label
}, ], 'value', 'label', false, );
}, false, );
$(document).on('click', '.ajax_data', function() {
let data = '1,1,2,3,3';
query_task.removeActiveItems();
query_task.setChoiceByValue(data.split(','));
console.log('Ajax data loaded');
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://choices-js.github.io/Choices/assets/styles/choices.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/choices.js/9.1.0/choices.min.js"></script>
<div class="row pt-2 px-5">
<div class="col-12 px-5">
<label for="query_task" class="form-label">SELECT TASKS</label>
<select id="query_task" class="form-control choices-multiple" multiple>
<option value="0">ZERO</option>
<option value="1">ONE</option>
<option value="2">TWO</option>
<option value="3">THREE</option>
<option value="4">FOUR</option>
</select>
<div>
<div>
<button type="button" class="ajax_data btn btn-primary">Load AJAX data</button>
</div>
</div>
Final result:
let query_data = [
{ value: "0", label: "ZERO" },
{ value: "1", label: "ONE" },
{ value: "2", label: "TWO" },
{ value: "3", label: "THREE" },
{ value: "4", label: "FOUR" }
];
document.addEventListener("DOMContentLoaded", function() {
const query_task = new Choices(document.querySelector('#query_task'), {
removeItemButton: true,
maxItemCount: 10,
choices: query_data
});
query_task.passedElement.element.addEventListener('addItem', () => reset(), false);
query_task.passedElement.element.addEventListener('removeItem', () => reset(), false);
function reset() {
query_task.clearChoices();
query_task.setChoices(query_data, "value", "label", false);
}
$(document).on('click', '.ajax_data', function() {
query_task.removeActiveItems();
let data = '1,1,2,3,3';
let selected_values = data.split(',')
$.each(selected_values, function(key, value) {
query_task.setChoiceByValue(value);
reset();
});
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://choices-js.github.io/Choices/assets/styles/choices.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/choices.js/9.1.0/choices.min.js"></script>
<div class="row pt-2 px-5">
<div class="col-12 px-5">
<label for="query_task" class="form-label">SELECT TASKS</label>
<select id="query_task" class="form-control choices-multiple" multiple>
</select>
<div>
<div>
<button type="button" class="ajax_data btn btn-primary">Load AJAX data</button>
</div>
</div>

The documentation is bit confusing 😵. There are two issues to fix:
To add duplicates you need to use setValue(items) method. Next point explains how to get rid of duplicates.
After you unselect an item it gets added back to the options list. This creates duplicate items. I couldn't find method to remove a single choice from options list. So as a workaround I am resetting entire options list.
Demo:
let labels = ['ZERO', 'ONE', 'TWO', 'THREE', 'FOUR'];
let query_task = null;
document.addEventListener("DOMContentLoaded", function() {
query_task = new Choices(document.querySelector('#query_task'), {
removeItemButton: true,
maxItemCount: 10,
duplicateItemsAllowed: true,
choices: defaults()
});
query_task.passedElement.element.addEventListener('addItem', function(e) {
query_task.setChoices([{
value: e.detail.value,
label: e.detail.label
}, ], 'value', 'label', false);
}, false);
query_task.passedElement.element.addEventListener('removeItem', () => reset(), false);
$(document).on('click', '.ajax_data', function() {
let data = '1,1,2,3,3';
query_task.removeActiveItems();
query_task.setValue(data.split(',').map((v) => ({value: v, label: labels[+v]})));
reset();
console.log('Ajax data loaded');
});
});
function defaults() {
return labels.map((lbl, i) => ({value: i, label: lbl}));
}
function reset() {
query_task.clearChoices();
query_task.setChoices(defaults(), 'value', 'label', false);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://choices-js.github.io/Choices/assets/styles/choices.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/choices.js/9.1.0/choices.min.js"></script>
<div class="row pt-2 px-5">
<div class="col-12 px-5">
<label for="query_task" class="form-label">SELECT TASKS</label>
<select id="query_task" class="form-control choices-multiple" multiple></select>
<div>
<div>
<button type="button" class="ajax_data btn btn-primary">Load AJAX data</button>
</div>
</div>
</div>
</div>

Hi #Crezzur,
Thanks for posting the question, I got to know this tiny yet useful library.(I am definitely using this in my next project)
I did some digging and it seems you can not use setChoicesByValue() for your requirement due to a check in the library reference code:here
However I achieved it by using setValue() instead. Here is a working stackblitz link for you

Related

Show and hide select dynamically

I return my select dynamically. I use the following code:
var data = [
{Id: "1", },
{Id: "2", },
{Id: "3", },
{Id: "4", },
{Id: "5", },
{Id: "6", },
];
$(document).on('click', '.dad-pagamento', function() {
var linha = ``;
for (var x = 0; x < data.length; x++) {
linha += `<div class="col-3">
<label id="atb11" style="margin-top: 5%;"><i class="pe-2x pe-va pe-7s-plus"></i> Ajudante</label>
<div id="atbb22" style="display:none;">
<select class="js-states form-control ajuste singlet" name="auxiliar[]">
<option></option>
<option value="${data[x].Id}">${data[x].Id}</option>
</select>
</div>
</div>`;
$(".pagmfalta").html(linha);
$('#minhaDiv1').show();
$(".singlet").select2({
placeholder: "Selecione Ajudante",
allowClear: true,
width: '100%'
});
$('#atb11').on('click', function() {
$('#atbb22').slideToggle('slow');
});
}
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/pixeden-stroke-7-icon#1.2.3/pe-icon-7-stroke/dist/pe-icon-7-stroke.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>
<button type="button" class="btn btn-info dad-pagamento" style="float: right; margin-right: 5%; margin-top: 4%;"><i class="metismenu-icon pe-7s-search"></i> Consultar </button>
<section id="s1">
<div style="display:none" id="minhaDiv1">
<div class="row pagmfalta">
</div>
</div>
</section>
I use this code to show and hide the select:
$('#atb11').on('click', function() {
$('#atbb22').slideToggle('slow');
});
The problem as it returns more than one select and I am using id, it only opens the first select and not the others.
I intend to open select one by one according to my needs. I don't want to click on a select and they all open
As I mentioned in the comments, you have some id for multiple elements. You have to append the index variable x with id to make ids unique for each element. Secondly, add .on(click) that delegates the event for both current and future elements.
check: This answer
See the working example below:
var data = [
{Id: "1", },
{Id: "2", },
{Id: "3", },
{Id: "4", },
{Id: "5", },
{Id: "6", },
];
$(document).on('click', '.dad-pagamento', function() {
var linha = ``;
for (var x = 0; x < data.length; x++) {
linha += `<div class="col-3">
<label id="atb11-${x}" style="margin-top: 5%;"><i class="pe-2x pe-va pe-7s-plus"></i> Ajudante</label>
<div id="atbb22-${x}" style="display:none;">
<select class="js-states form-control ajuste singlet" name="auxiliar[]">
<option></option>
<option value="${data[x].Id}">${data[x].Id}</option>
</select>
</div>
</div>`;
$(".pagmfalta").html(linha);
$('#minhaDiv1').show();
$(".singlet").select2({
placeholder: "Selecione Ajudante",
allowClear: true,
width: '100%'
});
$(document).on('click','#atb11-'+x,function(e){
e.stopImmediatePropagation(); //Keeps the rest of the handlers from being executed
$(this).next().slideToggle('slow');
});
}
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/pixeden-stroke-7-icon#1.2.3/pe-icon-7-stroke/dist/pe-icon-7-stroke.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>
<button type="button" class="btn btn-info dad-pagamento" style="float: right; margin-right: 5%; margin-top: 4%;"><i class="metismenu-icon pe-7s-search"></i> Consultar </button>
<section id="s1">
<div style="display:none" id="minhaDiv1">
<div class="row pagmfalta">
</div>
</div>
</section>
The issue you mentioned in comments ( .on() is triggering event multiple times) can be solved by adding event.stopImmediatePropagation().
Check docs, It will stops rest of the handlers from being executed.

How to render an array inside another object array with Vue Js

I am working with Laravel Vuejs, and from my database I obtain an object array called arrayService, through axios I perform a get where the array I obtain can be seen represented.
var app = new Vue({
el: '#app',
mounted() {
//this.getService()
},
data() {
return {
arrayService: [
{ service: '2', format: [".mp3",".mp4"] },
{ service: '3', format: [".jpg",".png"] },
],
arrayFormat: [".mp3",".mp4",".jpg",".png"]
}
},
methods:
{
getService() {
axios.get('/').then(function(response){
this.arrayService = response.data
/*I GET FROM THE DATABASE
arrayService: [
{ service: '2', format: [".mp3",".mp4"] },
{ service: '3', format: [".jpg",".png"] },
],
*/
$.each(response.data, function (key,value) {
$.each(JSON.parse( value.format ), (key,element) => {
this.arrayFormat.push(element)
/*RESULT OF PARSE:
arrayFormat: [
{ [".mp3",".mp4",".jpg",".png"] }
]
*/
})
})
})
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div id="app">
<div>
<div class="row">
<div class="col-sm-6">
<h5>Wrong result :</h5>
<div v-for="service in arrayService" :key="service.id">
<strong>Id Service:</strong> {{service.service}}
<br>
<strong>Format:</strong>
<div v-for="format in arrayFormat" :key="format.id">
{{format}}
</div>
</div>
</div>
<div class="col-sm-6">
<h5>Correct result:</h5>
<strong>Id Service:</strong> 2
<br>
<strong>Format:</strong>
<br>
.mp3
<br>
.mp4
<br>
<strong>Id Service:</strong> 3
<br>
<strong>Format:</strong>
<br>
.jpg
<br>
.png
<br>
</div>
</div>
<br>
<br>
<br>
<br><br>
<br>
<br>
<br>
<br>
<br>
</div>
</div>
When I store the array arrayService, what I do is a Parse, inside the format attribute, since there is another array with the formats of each service. (see comments).
By doing this Parse, I finally do a push to store all these elements (formats) in an array called arrayFormat.
The problem I am having is that when doing that push, it stores everything together, and it is not what I am looking for.
What I am looking for is to store each format, regarding its service.
In the HTML view I tried to show the correct result, but the idea is to put all this together with VueJS.
Any idea?
You don't need the arrayFormat array at all, since the data structure you need is already in the API response.
You can iterate the nested array (service.format) directly:
<div v-for="service in arrayService" :key="service.service">
... 👇
<div v-for="format in service.format" :key="format">
{{format}}
</div>
</div>
new Vue({
el: '#app',
data() {
return {
arrayService: [{
service: '2',
format: [".mp3", ".mp4"]
},
{
service: '3',
format: [".jpg", ".png"]
},
],
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div id="app">
<div v-for="service in arrayService" :key="service.service">
<strong>Id Service:</strong> {{service.service}}
<br>
<strong>Format:</strong>
<div v-for="format in service.format" :key="format">
{{format}}
</div>
</div>
</div>

Animation of each element separately in the v -for loop (Vue.JS)

I made a simple todo app using VueJS.
I also added vue2-animate (A Vue.js 2.0 port of Animate.css. For use with Vue's built-in transitions.)
Animation of adding one element works correctly.
But there were two problems that I would like to solve without unnecessary coding:
Animation display for the list of downloaded from local storage
works for all items simultaneously. I need the animation to work
sequentially for each item separately.
Animation of deleting an item does not work correct - the last
item is always removed, and then a shift follows.
P.S.: Look demo in JSFiddle, because localstorage don't work in SO snippets.
Vue.component("adder", {
data: function() {
return {
task: ""
};
},
template: `
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="New task..." aria-label="New task..." aria-describedby="" v-model="task" v-on:keyup.enter="add">
<div class="input-group-append">
<button class="btn btn-primary" id="" v-on:click="add" >+</button>
</div>
</div>
`,
methods: {
add: function() {
this.$emit("addtodo", {
title: this.task,
done: false
});
this.task = "";
}
}
});
Vue.component("todo", {
props: ["item"],
template: `
<a href="#" class="list-group-item list-group-item-action task" v-bind:class="{'disabled done' : item.done==true}">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="" id="" value="checkedValue" v-model="item.done"> {{item.title}}
</label>
<button type="button" class="close" aria-label="Close" v-on:click="del">
<span aria-hidden="true">×</span>
</button>
</a>
`,
methods: {
del: function() {
this.$emit("deletetodo");
}
}
});
Vue.component("todos", {
props: ["items"],
template: `
<div class="list-group">
<transition-group name="bounceLeft" tag="a">
<todo v-for="(item, index) in items" :key="index" :item.sync="item" v-on:deletetodo="delTodo(item)"></todo>
</transition-group>
</div>
`,
methods: {
delTodo: function(i) {
this.$emit("deletetodo", i);
}
}
});
Vue.config.devtools = true;
let app = new Vue({
el: ".todoapp",
data: {
title: "Todo App",
items: []
},
methods: {
addTodo: function(e) {
this.items.push(e);
},
delTodo: function(i) {
this.items = this.items.filter(e => e != i);
}
},
mounted() {
if (localStorage.items) {
this.items = JSON.parse(localStorage.getItem("items"));
}
},
watch: {
items: {
handler(val) {
localStorage.setItem("items", JSON.stringify(this.items));
},
deep: true
}
}
});
.done>label {
text-decoration: line-through;
}
.task {
padding-left: 36px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Todo App</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous" />
<link rel="stylesheet" href="https://unpkg.com/vue2-animate/dist/vue2-animate.min.css" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container todoapp">
<div class="row">
<br />
</div>
<div class="card">
<div class="card-header">
{{ title }}
</div>
<div class="card-body">
<adder v-on:addtodo="addTodo"></adder>
<todos :items.sync="items" v-on:deletetodo="delTodo"></todos>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<script src="script.js"></script>
</body>
</html>
JSFiddle demo
Ok taking this one at a time:
Deleting a task
The reason it always seems to be the last task being removed is because you are keying your list items by index. When you replace the whole items array in your delTodo method that in turn gives you a new array with new keys for each item in the list. Key by item and you'll get the right result:
<todo v-for="(item, index) in items" :key="item" :item.sync="item" v-on:deletetodo="delTodo(item)"></todo>
Showing tasks one at a time on load
My advice would be to approach the showing/hiding of tasks with a computed property:
computed: {
tasks: function(){
return this.items.filter(item => item.isVisible);
}
}
Here we'll show/hide by toggling isVisible on each task.
This means when you initially load the tasks from local storage you could set them all to isVisible: false and then use a setTimeout in a for loop to display them all one at a time:
mounted() {
// Get your items and set all to hidden
if (localStorage.items) {
this.items = JSON.parse(localStorage.getItem("items"))
.map(item => item.isVisible = false);
}
// Loop through and show the tasks
for(let i=1; i<=this.items.length; i++){
// Where 300 is milliseconds to delay
let delay = i * 300;
setTimeout(function(){
this.items[i].isVisible = true;
}.bind(this), delay);
}
},
Best of all, phased addition to the items array worked:
mounted() {
let items = [];
if (localStorage.items) {
items = JSON.parse(localStorage.getItem("items"))
}
for (let i = 0; i < items.length; i++) {
let delay = i * 1000;
setTimeout(
function() {
this.items.push(items[i])
}.bind(this),
delay
)
}
}
Just to add to the conversation, the following achieves the staggering within a Vuex's Action and using fat arrow syntax:
async fetchRepositories( {commit} ){
const response = await gitHubApi.get<Repository[]>('/users/rodolphocastro/repos') // Calling API with Axios
const staggered: Repository[] = []
response.data.forEach((r, i) => {
const delay = i * 300 // 300m -> Time to wait for each item in the array
setTimeout(() => {
staggered.push(r)
commit('setRepositories', staggered)
}, delay)
})
}

jquery chosen in bootstrap popover not working

I am trying to run jquery chosen inside a bootstrap popover, but the initiated chosen dropdown is not clickable.
Here is my code:
html
<button type="button" class="btn btn-md btn-danger" id="popover" data-title="Popover title" >Click to toggle popover</button>
<div style="display: none;" id="popovercontent">
<select class="chosen chzn-done">
<option>Choose...</option>
<option>jQuery</option>
<option selected="selected">MooTools</option>
<option>Prototype</option>
<option>Dojo Toolkit</option>
</select>
</div>
JS
$(document).ready(function(){
// init chosen
var $chosen = $(".chosen").chosen();
// init popover
var $popover = $('#popover').popover({
placement: 'bottom',
html: true,
content: function () {
return $('#popovercontent').html();
},
title: function () {
return $(this).data('title');
},
});
// on show popover
$popover.on("show.bs.popover", function(e) {
console.log('open popover');
$chosen.trigger("chosen:updated");
});
}); // document.ready
https://jsfiddle.net/gdtocsud/
similar question (not answered): Chosen in bootstrap popover not working?
thank you
Bjoern
try this, may be this will help u
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.6.2/chosen.jquery.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.6.2/chosen.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.6.2/chosen.css">
<script>
$(document).ready(function() {
var $popover = $('#popover').popover({
placement: 'bottom',
html: true,
content: function() {
return $('#popovercontent').html();
},
title: function() {
return $(this).data('title');
},
});
$popover.on("shown.bs.popover", function(e) {
$('.chzn-done').chosen();
});
$popover.on('hidden.bs.popover', function() {
$('.chzn-done').chosen('destroy');
});
});
</script>
</head>
<body style="padding:25px">
<button type="button" class="btn btn-md btn-danger" id="popover" data-title="Popover title">Click to toggle popover</button>
<div id="popovercontent" style='display:none'>
<select class="chosen chosen-select chzn-done" >
<option>Choose...</option>
<option>jQuery</option>
<option selected="selected">MooTools</option>
<option>Prototype</option>
<option>Dojo Toolkit</option>
</select>
</div>
</body>
</html>
Here is the js code :
$(document).ready(function() {
// init chosen
//var $chosen = $(".chosen").chosen();
// init popover
var $popover = $('#popover').popover({
placement: 'bottom',
html: true,
content: function() {
return $('#popovercontent').html();
},
title: function() {
return $(this).data('title');
},
});
// on show popover
$popover.on("shown.bs.popover", function(e) {
$('.chzn-done').chosen();
});
$popover.on('hidden.bs.popover', function() {
$('.chzn-done').chosen('destroy');
});
}); // document.ready
For working code:
Here is fiddle link
Similar to chosen with modal the chosen behaviour needs to be initialized after the content is ready, so similar to modal events, you can use the popover events
Hi here is the working demo
https://jsfiddle.net/gdtocsud/2/
<div class="panel panel-default">
<div class="panel-body">
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span data-bind="label">Select One</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li>Item 1</li>
<li>Another item</li>
<li>This is a longer item that will not fit properly</li>
</ul>
</div>
</div>
</div>

How to add a link in javascript

I have the following Javascript that I am using to make a sort of flowchart where the user clicks through a set of questions. For certain responses i want to link to an external site where more info can be found. How do I add these links?
HTML
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div class="wrapper">
<div class="container">
<div class="row">
<div class="col-xs-12 text-right">
<button class="btn btn-default btn-corner" type="submit" data-bind="click: startOver, visible: queryData().id > 0">Start over</button>
</div>
</div>
</div>
<div class="container main">
<div class="row">
<div class="c12 text-center">
<h1 data-bind="text: queryData().text"></h1>
<h3 data-bind="text: queryData().subhead"></h3>
<div class="option-group" data-bind="foreach: queryData().answers">
<button class="btn btn-default btn-lg" type="submit" data-bind="click: $parent.goToTarget, text: text"></button>
</div>
<button class="btn btn-default" type="submit" data-bind="click: stepBack, visible: navHistory().length > 1">Previous Step</button>
</div>
</div>
</div>
<div class="push"></div>
</div>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.3.0.js"></script>
<script src="app.js?v=0.4.0"></script>
<script>
</script>
</body>
</html>
The Javascript is as follows:
JS
var queries = [{
id: 0,
text: "Where to start?",
answers: [{
text: "Let's Begin!",
target: 1
}]
}, {
id: 1,
text: "Which genre do you want to start in?",
answers: [{
text: "Fantasy",
target: 100
}, {
text: "SciFi",
target: 2
}, {
text: "Neither",
target: 59
}]
}, {
id: 2,
text: "It's huge but it's worth it. The Cryptonomicon by Neal Stephenson",
answers: [{
text: "Amazon.co.uk",
target: "_blank"
}, {
text: "Amazon.com"
}]
}];
function QueryViewModel() {
var self = this;
self.querySet = ko.observable();
self.currentStep = ko.observable();
self.queryData = ko.observable();
self.sfw = ko.observable();
self.navHistory = ko.observableArray();
// Operations
self.goToTarget = function(obj) {
self.navHistory.push(self.currentStep());
self.currentStep(obj.target);
self.queryData(self.querySet()[obj.target]);
}
self.startOver = function() {
self.navHistory.removeAll();
self.goToTarget({target: 0});
}
self.stepBack = function() {
var lastStep = self.navHistory().length > 1 ? self.navHistory.pop() : 0;
self.currentStep(lastStep);
self.queryData(self.querySet()[lastStep]);
}
var paramsString = document.location.hash.substring(1);
var params = new Array();
if (paramsString) {
var paramValues = paramsString.split("&");
for (var i = 0; i < paramValues.length; i++) {
var paramValue = paramValues[i].split("=");
params[paramValue[0]] = paramValue[1];
}
}
params ? paramTarget = params['target'] : params = [];
self.sfw() ? self.querySet(queriesSFW) : self.querySet(queries);
if (paramTarget) {
self.navHistory.push(0);
self.currentStep(0);
self.goToTarget({target: paramTarget})
} else {
self.goToTarget({target: 0});
}
}
ko.applyBindings(new QueryViewModel());
In html you can do something like this:
<button type="button" onclick="window.open('https://google.com/', '_self')">Button</button>
You don't have to use a button, different elements can use onclick like text or images. This can also call js functions, just put the function name where "window.open..." is.
Of course the standard way to do it is
<a href='https://www.google.com/'>Link</a>
You can practice using js here: http://www.w3schools.com/js/tryit.asp?filename=tryjs_intro_inner_html
and learn more about it here: http://www.w3schools.com/js/js_intro.asp
I am not sure why you would show us the JSON for open a link to another page. Unless I misunderstood. This kind of basic information can be found by a quick Google search.
Add your link in the object like:
text: "Fantasy",
link: "http://www.stackoverflow.com",
target: 2
Now when you need to go to that link, use this function:
var link = obj.link;
window.open(link, "_blank");

Categories