Adding comma after each word in JavaScript - javascript

I have selected tag input and I can choose multiple items using MagicSuggest plugin.
The problem is that the value that I get after the choice is a string separated without a comma.
Like:
MVCPHPASP.Net
I want to change it to:
MVC,PHP,ASP.Net
The result that I get when I choose multiple items :
The string that I get when I alert :
So how can I do that?

The right way is to get the data using the plugin's API, not weird parsing.
According the docs you can use the function .getSelection() to get the selected items.
var ms = $('#ms-getValue').magicSuggest({
data: [
{
id: 1,
name: 'Paris'
},
{
id: 2,
name: 'New York'
},
{
id: 3,
name: 'Gotham'
}
]
});
function getValues() {
// array
var selected = ms.getSelection();
alert(selected.map(function(item) {
return item.name;
}).join(','));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://nicolasbize.com/magicsuggest/lib/magicsuggest/magicsuggest.css" rel="stylesheet" />
<script src="http://nicolasbize.com/magicsuggest/lib/magicsuggest/magicsuggest.js"></script>
<div id="ms-getValue"></div>
<button onclick="getValues()">Get Values</button>
Update The result is an Array. So, to get the first (for example) selected object you do: selected[0].name
Update 2
To show all the selected values separated by comma:
selected.map(function(item) {
return item.name;
}).join(',')

Related

Filter Suggestion Items using Key in SAPUI5

I've implemented a suggestion items for an input field inside a table and it's working fine. Also, i've implemented the event "SuggestionItemSelected" to get the additional text of the suggested item to display the description of the code.
SuggestItemSelected event will trigger only if we select the suggested item from the list and then we could get the text of the code selected.
So how to get the text of the entered code if we enter the data directly in the input field without using suggestion items? I know we could get the value of the input field by reading "byId()" but not getting how to get the associated text.
I've tried to filter the suggestion items with the selected key value but it wouldn't work. Kindly help to filter the suggestion items on key value to get the associated text of it.
Suggestion Items Array
I played a bit around with the suggestions and it looks like if:
you type very fast and press enter before suggestion opens, onSuggestionItemSelected is not called.
leave (mouse click somewhere else) onSuggestionItemSelected is not called.
You could simply check getSelectedKey()and refuse this user input with a message like "use a suggestion".
Anyhow, there is a way to filter afterwards based on the input for a suggestion item key; see my example.
But keep in mind that getSuggestionItems() returns 0 items if the suggestions http-request is still in progress. Sadly ui5 has no promise api in place.
sap.ui.controller("view1.initial", {
onInit : function(oEvent) {
const oModel = new sap.ui.model.json.JSONModel();
oModel.setData({
rows : [
{ key: "1", col4 : "Value4" },
{ key: "2", col4 : "Value2" },
{ key: "3", col4 : "Value16" },
{ key: "4", col4 : "Value20" }
]
});
this.getView().setModel(oModel);
},
onChange: function(oEvent) {
const input = oEvent.getSource()
let selectedKey = input.getSelectedKey()
if(!selectedKey){
var dataObject =
selectedKey = input.getSuggestionItems()
.map( (suggestionItem)=> suggestionItem.getBindingContext().getObject() )
.find( (a)=> a.col4 === oEvent.getParameter("newValue") );
if(dataObject){
selectedKey = dataObject.key
console.log("found key:" + selectedKey)
}else{
console.warn("no matching key")
}
}else{
console.log("provided key:" + selectedKey)
}
},
onSuggestionItemSelected: function(oEvent) {
}
});
sap.ui.xmlview("main", {
viewContent: jQuery("#view1").html()
})
.placeAt("uiArea");
/* extra CSS classes here */
<script id="sap-ui-bootstrap"
src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-libs="sap.m"></script>
<div id="uiArea"></div>
<script id="view1" type="ui5/xmlview">
<mvc:View controllerName="view1.initial" xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc">
<Input
showSuggestion="true"
change="onChange"
suggestionItemSelected="onSuggestionItemSelected"
suggestionItems="{/rows}">
<suggestionItems>
<core:Item text="{col4}" key="{key}" />
</suggestionItems>
</Input>
</mvc:View>
</script>

Javascript: If then statement not working in function

I'm building a personality-type quiz and having difficulty tailoring the results page as I'd like it to. The if statement, contained in the display_scenario function, isn't working. I want it to generate a different final message depending on the value of the countValue variable but it's not working. If you are able to help me understand why it's not working, I'd appreciate it.
The key pieces of code are below. It's also in place on Codepen: http://codepen.io/msummers40/pen/eZaePe
Essentially, the quiz:
- asks people a series of questions
- each answer has a numeric weight assigned to it
- this numeric weight is tallied in the countValue variable
- I want to use the countValue variable as a way to generate one of four final pages
I've tried to set up an if statement at the end of the quiz but it's just not working and I'm unsure of how to get this to work - it seems to be building the final view regardless of what's in the if statement.
If you are able to help, thank you.
<body>
<!-- QUIZ BEGINS -->
<div id="wrapper">
<h2 id="cyoaHeader">TITLE HERE<br><small>SUBHED</small></h2>
<div id="quizImage"> </div>
<div id="prompt"> </div>
<div id="options"> </div>
<div id="buildingStatus"> </div>
</div>
<div id="addLinks"> </div>
<!-- QUIZ ENDS -->
<script>
// JSON for quiz
// Contains the questions, images and variable to give answers weight/direction
var story = {
intro: {
prompt: 'You need to get up and out and get on with a big task - what song would propel you out of bed?',
quizImage: '<img id="quizImage" src="https://upload.wikimedia.org/wikipedia/commons/a/ab/Semi-nude_woman_getting_out_of_bed_(rbm-QP301M8-1887-265a~5).jpg"><br />',
options: [{
name: 'Song 4',
path: 'questionTwo',
addition: 4
}, {
name: 'Song 3',
path: 'questionTwo',
addition: 2
}, {
name: 'Song 2',
path: 'questionTwo',
addition: 3
}, {
name: 'Song 1',
path: 'questionTwo',
addition: 1
}]
},
questionTwo: {
prompt: 'Sentence.<br/><br/>Question 2?',
quizImage: '<img id="quizImage" src="http://www.allgifs.com/wp-content/uploads/2013/09/pancake.gif">',
options: [{
name: 'A',
path: 'result',
addition: 4
}, {
name: 'B',
path: 'result',
addition: 3
}, {
name: 'C',
path: 'result',
addition: 2
}, {
name: 'D',
path: 'result',
addition: 1
}]
},
result: {
prompt: 'This is the default statement on the results page. I need to make it tailored to the countValue variable',
quizImage: '<img id="quizImage" src="http://viralgifs.com/wp-content/uploads/2014/03/cat_did_u_forget.gif">',
options: [{
name: 'FINAL CTA',
path: 'intro',
addition: 0
}]
}
};
//establishing counter for weighted answer
var countValue = 0;
console.log(countValue);
var additionInt = 0;
console.log(additionInt);
// Option is an object with properties {name and path objects, addition array}
function display_scenario(options) { //value passed had been chosen_options
var option_name = options.name;
var option_path = options.path;
var additionInt = options.addition;
countValue += additionInt;
// countValue = (additionInt + countValue);
console.log(additionInt);
console.log(countValue);
var scenario = story[option_path];
// Clear the #prompt, #quizImage, #options, #addLinks, #buildingStatus divs before writing new ones in if statment below -- GROUP THESE IN A FUNCTION BEFORE GO LIVE
jQuery('#prompt').empty();
jQuery('#quizImage').empty();
jQuery('#options').empty();
jQuery('#addLinks').empty();
jQuery('#buildingStatus').empty();
// THIS IF ELSE STRUCTURE DOESN'T SEEM TO BE WORKING - I'M TRYING TO SET IT UP SO THAT IT DISPLAYS ONE OF FOUR OPTIONS, DEPENDING ON THE VALUE OF THE countValue VARIABLE. ATM ONLY THREE OPTIONS ARE IN PLACE; NONE ARE WORKING.
// Create a <p> to display what the user has chosen if option_name is not null and append it to the #prompt <div>
if (options.name != 'result') {
jQuery('<p>').html('<i>You selected <b>' + option_name + '</b></i><br><p>And the running total is ' + countValue + '</p>').appendTo('#buildingStatus');
// Append the scenario's prompt
jQuery('<p>').html(scenario.prompt).appendTo('#prompt');
// Appending an image
jQuery('<p>').html(scenario.quizImage).appendTo('#quizImage');
// Appending links in the addLinks div
jQuery('<div>').html(scenario.addLinks).appendTo('#addLinks');
} else if (options.name == 'result' && countValue<17) {
jQuery('<p>').html('<i>Yay! This option worked. You selected <b>' + option_name + '</b></i><br><p>And the running total is ' + countValue + '</p>').appendTo('#buildingStatus');
// Append the scenario's prompt
jQuery('<p>').html(scenario.prompt).appendTo('#prompt');
// Appending an image
jQuery('<p>').html(scenario.quizImage).appendTo('#quizImage');
// Appending links in the addLinks div
jQuery('<div>').html(scenario.addLinks).appendTo('#addLinks');
} else {
jQuery('<p>').html('<i>Yay! This option worked. You selected <b>' + option_name + '</b></i><br><p>And the running total is ' + countValue + '</p>').appendTo('#buildingStatus');
// Append the scenario's prompt
jQuery('<p>').html(scenario.prompt).appendTo('#prompt');
// Appending an image
jQuery('<p>').html(scenario.quizImage).appendTo('#quizImage');
// Appending links in the addLinks div
jQuery('<div>').html(scenario.addLinks).appendTo('#addLinks');
};
// Append the options into the #options <div>
// We want to loop through all the options and create buttons for each one. A regular for-loop would not suffice because adding a button is not asynchronous. We will create an asynchronous loop by using recursion
function add_option_button(index) {
if (index === scenario.options.length) {
// Base case
return;
}
var option = scenario.options[index];
// Create a <button> for this option and append it to the #options <div>
jQuery('<button>')
.html(option.name)
.click(function(e) {
// This is an onclick handler function. It decides what to do after the user has clicked on the button.
// First, prevent any default thing that the button is going to do, since we're specifying our own action for the button
e.preventDefault();
// We'll want to call display_scenario() with this option
display_scenario(option);
})
.appendTo('#options');
// Add the next option button
add_option_button(index + 1);
}
add_option_button(0);
}
// This function waits until the document is ready
jQuery(document).ready(function() {
// Start the quiz
display_scenario({
name: null,
path: 'intro',
addition: 0
});
});
</script>
</body>
</html>
I think you need to recalculate the sum whenever the user changes something, apart from displaying the scenarios everytime. Split the display_scenario function into one to display the options, and into separate logic to sum up all options choosen.

Using initSelection in select2 3.5.2 for custom filtering

I have a text field which uses select2. Here is the initialization:
$("#foo").select2({
createSearchChoice:function(term, data) {
if ($(data).filter(function() {
return this.text.localeCompare(term)===0;
}).length===0)
{return {id:term, text:term};}
},
initSelection : function (element, callback) {
var data = {id: element.val(), text: element.val()};
callback(data);
},
tags:[],
tokenSeparators: [","],
data: [...data goes here...]
});
In this field, the user is supposed to put in a number, or select items from a list. If an item that the user puts in doesn't appear on the list, it ought be created as a simple tag (id and text identical). This works.
What doesn't work is when I set the value programmatically:
myvar.find('.placeholder lorem-ipsum').val(number).trigger("change");
The way it works now, is that when I set it to any value, it takes it without complaint, making a new simple tag. However, if I were to remove the initSelection parameter completely, it would ignore unknown values, and use known values as taken from the list (where tags are complex - id and text are different).
How do I make it so that if the value I set to the field is found on the list, it will use the item, and otherwise make a simple tag? The way it works now (simple tags only) is sort-of acceptable, but I'd prefer it worked ideally.
EDIT:
I've made examples for how it works with and without the initSelection parameter.
http://jppk.byethost12.com/with.html
http://jppk.byethost12.com/without.html
In short, I want it to work like with.html when I push "Add New Item" and I want it to work like without.html when I push "Add Existing Item".
Here is my best interpretation of what you want.
JSFiddle
The trick is to append the element to the select field.
var array = ['foo', 'bar', 'baz']
$.each(array, function(key, value) {
appendSelect(value);
});
$("#foo").select2();
$('#submit').click(function() {
var val = $('#name').val();
$('#name').val('');
array.push(val);
appendSelect(val);
});
function appendSelect(value) {
$('#foo').append($("<option></option>").text(value));
}
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0-rc.1/css/select2.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0-rc.1/js/select2.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<div class='container'>
<select id='foo' multiple="multiple" class='form-control'></select>
<label>Input</label>
<input id='name' />
<button id='submit'>submit</button>
</div>
Much, much later, I found a solution that works right:
initSelection : function (element, callback) {
var eArr = element.val().split(",");
var data = [];
for (var i=0;i<eArr.length;i++) {
for (var j=0;j<preExistingData.length;j++) {
if (preExistingData[j]["id"] === eArr[i]) {
data.push(preExistingData[j]);
continue;
}
}
data.push({id: eArr[i], text: eArr[i]});
}
callback(data);
},
This not only checks if the value is among the pre-existing values (in which case it uses that item), but also if the value is a comma-separated list of values (in which case it properly encapsulates them as JS objects).

Ractive, two bindings on an <input>

Note: I'm not referring to "two way binding"
I'm using a ractive decorator (select2) to transform an input into a select2. The data I obtain through ajax are some records from the database, example:
[{id:1, name:"test", quantity:2, image:"image.jpg"},
{id:2, name:"bar", quantity:21, image:"image2.jpg"},
{id:3, name:"foo", quantity:21, image:"image3.jpg"}]
I format these object using select2's functions, formatResult and formatSelection
The element on which I'm using the decorator is something like this:
<input type="hidden" value="{{values}}" decorator="select2">
After the user select something, values will be equal to the ids of the selected object, (eg: values=1,3 if i select the first and the last records)
My question is: how can i obtain the full object that was selected? I was thinking about two bindings on the <input> (<input value="{{values}}" data-objects="{{objects}}"> so the decorator can save the full objects too, when the user select something. But when i debug the decorator, node._ractive.binding only shows value and not other attributes.
I solved it by saving the result of the ajax request in ractive, then matching the ids with the object ids to find the original objects.
Not the prettiest thing, but it works.
Ractive.decorators.select2.type.whatever = {
tags: [],
separator: "|",
ajax: {
url: "ajax_url",
data: function(searchterm, page) {
return {
searchterm: searchterm,
page: page,
};
},
results: function(data, page) {
//Here i save the records
ractive.set("data", data.records);
return {results: data.records, more: data.more};
}
}
};
var ractive = new Ractive({
el: "things",
template: "template",
});
ractive.observe("ids", function(ids) {
var data = ractive.get("data");
ids = ids.split("|");
//I can obtain the original objects
});
<script src="http://cdn.ractivejs.org/latest/ractive.js"></script>
<script src="https://rawgit.com/Prezent/ractive-decorators-select2/master/ractive-decorators-select2.js"></script>
<!-- select2, jquery missing -->
<script type="ractive-template" id="template">
<input type="hidden" value="{{ids}}" decorator="select:whatever">
</script>
<div id="things"></div>

Jquery - Array manipulation from a select box

I'm creating a tag suggestions function, depending of a category. So, I have a select box with a bunch of categories, when I select a category, I want to display the sub-categories (using an array obviously) in a list. Here's what I have now:
<select id="categorySelect">
<option value="6">Animal</option> //the value here is the category id
<option value="12">Music</option>
</select>
<ul id="suggestedTags">
</ul>
my JSON array:
var tagsMakers= [
{ category: 'Animal', suggestedTags: [
{ name: 'cat'},
{ name: 'dog' },
{ name: 'rabbit'}
]},
{ category: 'Music', suggestedTags: [
{ name: 'rock' },
{ name: 'rap' }
]}
];
$("#categorySelect").change(function(){
});
I'm still learning array manipulations, and I don't know where to start!
In words the logic is:
When I select a category, I want to display every suggested tags for that category in the li below. I also want to be able to chose multiple categories, so if I select both categories, I want the suggested tags for both to show.
Anyone have a little time to help?
Yeah, first bind an event to the select tag, and based on the value, display the list. Also remove the JSON structure, and build a hash instead:
tagMakers = {'Animal': ['Cat','Dog','Rabbit'], 'Music': ['rock','rap']}
$("#categorySelect").change(function() {
$("#suggestedTags").empty();
$(this).find(":selected").each(function() {
var selected = $(this).text();
$.each(tagMakers[selected].function(i,n) {
$("#suggestedTags").append("<li>"+n+"</li>");
});
});
});
Your array of tags doesn't have the category id, so I'll use the category name here. But, as a good practice, better if you put the category id in the categories array. Better yet if you use a object hash instead of an array.
function getCategoryByName(name){
//search in array.
for(var i = 0, len = tagsMakers.length; i < len; i++)
{
if (tagsMakers[i].category === name)
{
// found.
return tagsMakers[i];
}
}
// do not exists
return;
}
$("#categorySelect").change(function(){
// get the selected value
var current = $(this).val(),
suggestedTags = $("#suggestedTags"),
category;
// we do not have the category id on 'tagsMakers', so
// we need the category name.
current = $("option[value="+current+"]", this).text();
//search in array.
category = getCategoryByName(current);
//populate the suggested tags
suggestedTags.empty()
$.each(category.suggestedTags, function(i, tag) {
$("<li>" + tag.name + "</li>").appendTo(suggestedTags);
});
});​
jsFiddle: http://jsfiddle.net/vcZnu/
EDIT: If you can change your categories array by an object hash (better), so you can use the solution provided by #CupidVogel, otherwise use this, which resolve your problem as asked in your question.

Categories