I am programming an autocomplete function for a search bar that features names of places in Norway.
I collect the data from a REST api URL provided by a third party.
Example with input "st" and two results:
{
"sokStatus":{
"ok":"true",
"melding":""
},
"totaltAntallTreff":"81280",
"stedsnavn":[
{
"ssrId":"23149",
"navnetype":"By",
"kommunenavn":"Larvik",
"fylkesnavn":"Vestfold",
"stedsnavn":"Stavern",
"aust":"214841.84",
"nord":"6550500.29",
"skrivemaatestatus":"Godkjent",
"spraak":"NO",
"skrivemaatenavn":"Stavern",
"epsgKode":"25833"
},
{
"ssrId":"506202",
"navnetype":"By",
"kommunenavn":"Stord",
"fylkesnavn":"Hordaland",
"stedsnavn":"Stord",
"aust":"-32194.93",
"nord":"6665261.05",
"skrivemaatestatus":"Godkjent",
"spraak":"NO",
"skrivemaatenavn":"Stord",
"epsgKode":"25833"
}
]
}
I want to have the autocomplete array contain the "stedsnavn" features from all the returned results in the json file. so for the above example it would be [Stavern, Stord].
I built my code based off a template/tutorial i found online. When I run it now the autocomplete suggestion is the "totaltAntallTreff" feature so for the json above it would suggest 81280.
Edit: What I really need to know is how to properly query the json where I now only have response(data). I have tried several methods ($.map, $.each) but whenever I modify my code it ends up giving no autocomplete suggestions.
See my code below
$(function () {
var getData = function (request, response) {
$.getJSON(
"https://ws.geonorge.no/SKWS3Index/ssr/json/sok?antPerSide=5&eksakteForst=false&navn=" + request.term + "*",
function (data) {
(response(data));
});
};
var selectItem = function (event, ui) {
$("#myText").val(ui.item.value);
return false;
}
$("#myText").autocomplete({
source: getData,
select: selectItem,
minLength: 1,
change: function() {
$("#myText").val("").css("display", 2);
}
});
});
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.0/themes/base/jquery-ui.css" />
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.0/themes/base/jquery.ui.autocomplete.css" />
<script src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script src="http://code.jquery.com/ui/1.10.0/jquery-ui.js"></script>
<div id="menu-container">
<input type="text" id="myText" />
</div>
Given the JSON structure provided, you could get the result with the following:
let json_data = {
"sokStatus": {
"ok": "true",
"melding": ""
},
"totaltAntallTreff": "81280",
"stedsnavn": [{
"ssrId": "23149",
"navnetype": "By",
"kommunenavn": "Larvik",
"fylkesnavn": "Vestfold",
"stedsnavn": "Stavern",
"aust": "214841.84",
"nord": "6550500.29",
"skrivemaatestatus": "Godkjent",
"spraak": "NO",
"skrivemaatenavn": "Stavern",
"epsgKode": "25833"
},
{
"ssrId": "506202",
"navnetype": "By",
"kommunenavn": "Stord",
"fylkesnavn": "Hordaland",
"stedsnavn": "Stord",
"aust": "-32194.93",
"nord": "6665261.05",
"skrivemaatestatus": "Godkjent",
"spraak": "NO",
"skrivemaatenavn": "Stord",
"epsgKode": "25833"
}
]
}
let values = json_data.stedsnavn.map(item => item.skrivemaatenavn);
values.forEach(value => {
$("#list").append(`<li>${value}</li>`);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="list"><ul>
As to what json_data.stedsnavn.map(item => item.skrivemaatenavn); is doing:
json_data.stedsnavn.map(item => item.skrivemaatenavn);
// Get the "stedsnavn" key from the data, an array
// Map each object in the array to
// its "skrivemaatenavn" key
Related
As the title implies, I do have the following data:
{
"modelExample": [
{ "id": 0 },
{ "id": 1 },
{ "id": 2 }
]
}
The JSONModel has three entries, which essentially equates to 3 in length.
How do I get the length through an Expression Binding statement?
My Attempt:
<Text text="{ ${modelExample>/}.length}"
OK, here is a sample. Click on Run code snippet to see it in action:
sap.ui.require([
"sap/ui/core/Core",
], Core => Core.attachInit(() => sap.ui.require([
"sap/ui/core/Fragment",
"sap/ui/model/json/JSONModel",
], async (Fragment, JSONModel) => {
"use strict";
// sample XML definition:
const definition = '<ObjectStatus title="Length" text="{= ${/modelExample}.length}" class="sapMObjectStatusLarge sapUiTinyMargin" inverted="true" state="Information" xmlns="sap.m" />';
const control = await Fragment.load({ definition });
const model = new JSONModel({
modelExample: [
{ id: 0, /*...*/},
{ id: 1, /*...*/},
{ id: 2, /*...*/},
],
});
control.setModel(model).placeAt("content");
})));
<script id="sap-ui-bootstrap" src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core, sap.m"
data-sap-ui-async="true"
data-sap-ui-compatversion="edge"
data-sap-ui-theme="sap_fiori_3"
data-sap-ui-xx-waitfortheme="init"
></script>
<body id="content" class="sapUiBody"></body>
As you can see, I'm using text="{= ${/modelExample}.length}" which displays the correct length of the array:
If the model is named (e.g. "myModel"), it should be {= ${myModel>/modelExample}.length}.
Keep in mind that expression binding syntax requires {= (OneWay) or {:= (OneTime) at the beginning.
To actually make use of the expression binding, the bootstrap config bindingSyntax needs be set to "complex" or compatVersion to "edge", as mentioned in this post. E.g. in index.html:
<script id="sap-ui-bootstrap" data-sap-ui-compatversion="edge" ...>
I have 2 select2 controls, both has same data loaded into them
I know that $("#basic").val("44||four||another||data4").trigger("change") will set as "invalid"
I need to set "invalid" just by setting the value as 44.
Likewise when I specify 22 it must specify the selected as "bug"
Note that it should entirely match the first parameter of id string separated by ||, ie when $("#basic").val("44").trigger("change") should not select 444.
<!DOCTYPE html>
<html>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/js/select2.min.js"></script>
<select id="advanced">
</select>
<select id="basic">
</select>
<script>
var data = [
{
id: "11||first||another||data1",
text: 'enhancement'
},
{
id: "22||second||another||data2",
text: 'bug'
},
{
id: "33||third||another||data3",
text: 'duplicate'
},
{
id: "444||fourfour||another||data44",
text: 'Junk'
},
{
id: "44||four||another||data4",
text: 'invalid'
},
{
id: "55||five||another||data5",
text: 'wontfix'
}
];
$("#advanced").select2({
data: data
})
$("#basic").select2({
data: data
})
$("#basic").val("44").trigger("change")
</script>
</body>
</html>
you could create a selectValue function that wraps your change. That way you'd be able to select an option based on any value of the key.
selectValue = function (value) {
let id = data.find(item => {
let ids = item.id.split("||")
if(ids && ids.indexOf(value) !== -1)
return true
})
// you need this check in case no id was found
if(id) {
id = id.id
$("#basic").val(id).trigger("change")
}
}
//usage
selectValue("44")
If data isn't a global variable make sure to add it as a function argument
selectValue = function (data, value) {
let id = data.find(item => {
let ids = item.id.split("||")
if(ids && ids.indexOf(value) !== -1)
return true
})
// you need this check in case no id was found
if(id) {
$("#basic").val(id.id).trigger("change")
}
}
//usage
selectValue(data, "44")
Also this assumes that another part of your key was just a placeholder. All parts of your id would need to be unique from each other for this to work.
Using attributeStartsWith selector
var data = [{"id":"11||first||another||data1","text":"enhancement"},{"id":"22||second||another||data2","text":"bug"},{"id":"33||third||another||data3","text":"duplicate"},{"id":"444||fourfour||another||data44","text":"Junk"},{"id":"44||four||another||data4","text":"invalid"},{"id":"55||five||another||data5","text":"wontfix"}];
$("#advanced").select2({
data: data
})
$("#basic").select2({
data: data
})
$("#basic option[value^=44]").prop('selected', true).trigger("change")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/js/select2.min.js"></script>
<select id="advanced"></select>
<select id="basic"></select>
I'm building a firefox web extension and I'd like to give its users some options that they can check/uncheck. The state of the checkboxes is saved locally via the WebExtensions storage API, but I'm not quite sure how to restore the saved state for each option.
Here is the options.html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form method="post">
<fieldset>
<legend>My favorite veggies</legend>
<input type="checkbox" name="eggplant" id="eggplant" />Eggplant<br />
<input type="checkbox" name="zucchini" id="zucchini" />Zucchini<br />
<input type="checkbox" name="tomatoe" id="tomatoe" />Tomatoe<br />
<input type="submit" value="Submit" />
</fieldset>
</form>
<script src="options.js"></script>
</body>
</html>
The options.js file that saves/restores the state of the checkboxes is as follows:
function onError(error) {
console.log(`Error: ${error}`);
}
function saveOptions(e) {
// List of search engines to be used
let eggplant = {
name: "Eggplant",
imageUrl: "https://www.organicfacts.net/wp-content/uploads/2013/06/Eggplant-1020x765.jpg",
show: form.eggplant.checked
};
let zucchini = {
name: "Zucchini",
imageUrl: "https://www.organicfacts.net/wp-content/uploads/zucchini.jpg",
show: form.zucchini.checked
};
let tomatoe = {
name: "Tomatoe",
imageUrl: "https://www.organicfacts.net/wp-content/uploads/2013/05/Organictomato1-1020x765.jpg",
show: form.tomatoe.checked
};
let setting = browser.storage.sync.set({
eggplant,
zucchini,
tomatoe
});
setting.then(null,onError);
e.preventDefault();
}
function restoreOptions() {
var gettingItem = browser.storage.sync.get({
'show'
});
gettingItem.then((res) => {
document.getElementById("eggplant").checked = eggplant.show;
document.getElementById("zucchini").checked = zucchini.show;
document.getElementById("tomatoe").checked = tomatoe.show;
});
}
document.addEventListener('DOMContentLoaded', restoreOptions);
document.querySelector("form").addEventListener("submit", saveOptions);
Here's the state of your storage after the set operation:
{
eggplant: {
name: "Eggplant",
imageUrl: "https://www.organicfacts.net/wp-content/uploads/2013/06/Eggplant-1020x765.jpg",
show: true
},
zucchini: { /* ... */ },
tomatoe: { /* ... */ }
}
However, in restoreOptions, you query the storage with the key "show" - or, more specifically, with a syntactically incorrect object literal {"show"}.
Even if you fix it to be "show" is no such top-level key (and that's the only type of query you're allowed), so the result comes up as empty.
If you want to query the entire storage, pass null.
If you want to query a single top-level key, pass it as a string.
If you want a set of top-level keys you know in advance, pass an array of key strings.
If you want to provide a default in case the key is not in storage, pass an object mapping keys to defaults.
Here's how to organize your code with using defaults:
const defaults = {
eggplant: {
name: "Eggplant",
imageUrl: "(redacted for brevity)",
show: false
},
zucchini: {
name: "Zucchini",
imageUrl: "(redacted for brevity)",
show: false
},
tomatoe: {
name: "Tomatoe",
imageUrl: "(redacted for brevity)",
show: false
}
};
function saveOptions() {
let settings = {}
for (let setting in defaults) {
settings[setting] = {
...defaults[setting], // spread the default values
show: form[setting].checked // override show with real data
}
}
browser.storage.sync.set(settings).then(null, onError);
}
function restoreOptions() {
browser.storage.sync.get(defaults).then(
(data) => {
document.getElementById("eggplant").checked = data.eggplant.show;
document.getElementById("zucchini").checked = data.zucchini.show;
document.getElementById("tomatoe").checked = data.tomatoe.show;
}
);
}
Of note: don't use submit and preventDefault, just use type="button" inputs and click.
Small edit: Object spread (...defaults[setting]) is still experimental (though supported in recent Chrome/FF), a more ES6-compliant code would be
for (let setting in defaults) {
// shallow copy default settings
settings[setting] = Object.assign({}, defaults[setting]);
// override show property
settings[setting].show = form[setting].checked;
}
Less concise, somewhat more compatible.
I am new to django.
From my findings, I tried this way, but didn't work.
<script type="text/javascript" >
var data = {{json}}
</script>
I am trying to use data table from this website, http://www.datatables.net/manual/data.
<script type="text/javascript" class="init">
var temp = '{{campaignList|escapejs}}'; // should be a list, but becomes a string
alert(typeof temp)
$(document).ready( function () {
$('#campaigns').DataTable({
data: temp,
columns: [
{ data: 'id' },
{ data: 'name' },
{ data: 'date' },
]
});
} );
</script>
When I check the type before passing into datatable, the type becomes string.
I also tried {{campaignList|escapejs}} without quote, but didn't work.
Any suggestion? Thanks.
If campaignList is a json string, pass it to safe filter to prevent escape:
var data = {{ campaignList|safe }};
I'm using the sfWidgetFormDoctrineJQueryAutocompleter from the sfFormExtraPlugin, an try to bind some event to the widget.
According to http://jqueryui.com/demos/autocomplete/#event-search there is a way to bind an event to the launch of a search.
However, it doesn't seems to work on the widget.
My code:
$this->widgetSchema['author_id'] = new sfWidgetFormDoctrineJQueryAutocompleter(array(
'model' => 'Employee',
'method' => 'getFullName',
'method_for_query' => 'findOneByEmployeeNumber',
'url' => '/backend_dev.php/employee/search',
'config' => '{
minChars: 3,
search: function(event, ui) { alert("Search!"); } //Should popup an alert() when the search is launched.
}'
));
However, when I fill the form, the search is launched, results are shown, but no alert is displayed.
Any ideas ?
Thanks.
Edit
Generated Javascript:
<label for="document_author_id">Author</label>
<input type="hidden" id="document_author_id" value="00000006" name="document[author_id]">
<input type="text" id="autocomplete_document_author_id" value="Michaƫl Jones" name="autocomplete_document[author_id]" autocomplete="off" class="ac_input">
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery("#autocomplete_document_author_id")
.autocomplete('/backend_dev.php/employee/search', jQuery.extend({}, {
dataType: 'json',
parse: function(data) {
var parsed = [];
for (key in data) {
parsed[parsed.length] = { data: [ data[key], key ], value: data[key], result: data[key] };
}
return parsed;
}
}, {
minChars: 3,
search: function(event, ui) { alert("Search!"); }
}))
.result(function(event, data) { jQuery("#document_author_id").val(data[1]); });
});
</script>
Try to put this at the end of your form.php (?) template
<?php javascript_tag(); ?>
jQuery().ready(function(){
// or use ID #autocomplete_document_author_id
jQuery(".ac_input").search(function(event, ui){
alert("Search!");
});
});
<?php end_javascript_tag(); ?>