twitter typeahead.js autocomplete remote not working - django

I have a site with stocks. I would like to add typeahead functionality to my bootstrap template. Since there are about 5000 stocks and will be even more in the future. I am using haystack with whoosh index. I should be using remote version of typeahead.js, but it is not working. Could you please take a look and tell me what am I missing?
<script type="text/javascript">
var stocks = new Bloodhound({
datumTokenizer: function (datum) {
return Bloodhound.tokenizers.whitespace(datum.name);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: "/search/autocomplete/",
replace: function(url, query) {
return url + "?q=" + query;
},
filter: function(stocks) {
return $.map(stocks, function(data) {
return {
tokens: data.tokens,
symbol: data.symbol,
name: data.name
}
});
}
}
});
stocks.initialize();
$('.typeahead').typeahead(null, {
name: 'stocks',
displayKey: 'name',
minLength: 1, // send AJAX request only after user type in at least X characters
source: stocks.ttAdapter()
});
</script>
This is my form
<form class="input-prepend" method="get" action="/search/">
<div id="remote">
<button type="submit" class="btn">Search</button>
<input type="text" class="typeahead" id="id_q" placeholder="Stock symbol or name" autocomplete="off" name="q">
</div>
</form>
Urls.py
url(r'^search/autocomplete/', 'stocks.views.autocomplete'),
url(r'^search/', include('haystack.urls')),
autocomplete view
from haystack.query import SearchQuerySet
import json
def autocomplete(request):
sqs = SearchQuerySet().autocomplete(content_auto=request.GET.get('q', ''))[:5]
array = []
for result in sqs:
data = {"symbol": str(result.symbol),
"name": str(result.name),
"tokens": str(result.name).split()}
array.insert(0, data)
return HttpResponse(json.dumps(array), content_type='application/json')
json response:
[{"tokens": ["Arbor", "Realty", "Trus"], "symbol": "ABR", "name": "Arbor Realty Trus"}, {"tokens": ["ABM", "Industries", "In"], "symbol": "ABM", "name": "ABM Industries In"}, {"tokens": ["AmerisourceBergen"], "symbol": "ABC", "name": "AmerisourceBergen"}, {"tokens": ["ABB", "Ltd", "Common", "St"], "symbol": "ABB", "name": "ABB Ltd Common St"}, {"tokens": ["Allianceberstein"], "symbol": "AB", "name": "Allianceberstein "}]
This is my domain name: digrin.com and this is autocomplete url.
What am I missing?

I can see two problems:
1) Your script declaration is missing a type attribute:
<script src="http://code.jquery.com/jquery-1.11.0.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.js"></script>
<script type='text/javascript' src="http://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script>
add "type='text/javascript'" to the script declarations for jquery and bootstrap.
A more modern way of declaring your script tags can be found here.
2) To initialise Typeahead you need to place the code into your jQuery ready method i.e.
$(function(){
var stocks = new Bloodhound({
datumTokenizer: function (datum) {
return Bloodhound.tokenizers.whitespace(datum.name);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: "/search/autocomplete/",
replace: function(url, query) {
return url + "?q=" + query;
},
filter: function(stocks) {
return $.map(stocks, function(data) {
return {
tokens: data.tokens,
symbol: data.symbol,
name: data.name
}
});
}
}
});
stocks.initialize();
$('.typeahead').typeahead(null, {
name: 'stocks',
displayKey: 'name',
minLength: 1, // send AJAX request only after user type in at least X characters
source: stocks.ttAdapter()
});
});
As it is currently the typeahead code wont get loaded.

Related

vue3 filtered data on computed with chartjs

im learning about vuejs 3 and for example i want to show a chartjs with a combo to filter data. (Without the combo, everything works correctly)
i have a parent component chartjs.vue where import the chartjs and the combo. when i select a year, i change the variable and show it on the template
<script setup>
import ChartJsBarChart from '#/views/charts/chartjs/ChartJsBarChart.vue'
import SelectYear from '#/componentes/selectYear.vue'
const api = ref('exp')
const year = ref([])
function selectYear(x) {
year.value = x
}
</script>
<template>
<!-- 👉 Latest Statistics -->
<VCol cols="24" md="12">
<VCard>
<VCardItem class="d-flex flex-wrap justify-space-between gap-4">
<VCardTitle>Choose a year</VCardTitle>
</VCardItem>
<VCardText>
<SelectAno #input="selectAYear" />
</VCardText>
</VCard>
</VCol>
<VCol cols="24" md="12">
<VCard>
<VCardItem class="d-flex flex-wrap justify-space-between gap-4">
<VCardTitle>Total</VCardTitle>
</VCardItem>
<VCardText>
<ChartJsBarChart :yearSelected="year" :url="api" />
</VCardText>
</VCard>
</VCol>
</template>
one child component with a select (to try props and emit) selectYear.vue
<script setup>
import { ref, defineEmits, watch } from 'vue'
const emit = defineEmits(['input'])
let selected = ref([])
const years = [
'2005',
'2008',
'2009',
'2010',
'2011',
'2012',
'2014',
'2015',
'2016',
'2017',
'2018',
'2019',
'2020',
'2021',
'2022',
'2023',
]
watch(
() => selected.value,
(newValue, oldValue) => {
change(newValue)
},
)
const change = val => emit('input', val)
</script>
<template>
<VSelect
v-model="selected"
:items="years"
label="choose a year"
/>
</template>
and last child component with the chartjs ChartJsBarChart.vue
<script setup>
import BarChart from '#/libs/chartjs/components/BarChart'
import axios from '#axios'
import { ref, onMounted, computed } from "vue"
import { useStatesStore } from '#/store/states'
const props = defineProps({
url: {
type: null,
required: true,
},
yearSelected: {
type: null,
required: true,
},
})
const apiData = ref([]) //data from API
const data = ref({}) // data parsed to chartjs
const store = useStatesStore()
const states = ref(store.states) // legend
const filterByYear = computed(() => {
return apiData.value.filter(item => item.year === '2005')
})
onMounted(async () => {
await axios
.get('/api/dashboard/expProvActiv')
.then(res => {
apiData.value = res.data['hydra:member']
})
})
</script>
<template>
{{ props.yearSelected }}
<hr>
{{ apiData }}
<BarChart
:height="400"
:chart-data="data"
/>
</template>
the result (shortened) of {{ apiData }} with hundred of items is:
[ { "state": "state 1", "activity": "string", "subactivity": "string", "year": 2015, "surface": "3.5500", "total": 3, "rcs": 3 }, { "state": "state 2", "activity": "string", "subactivity": "string", "year": 2016, "surface": "10.9400", "total": 13, "rcs": 13 }]
if i try to show filterByYear, the first time i have not data and how can i do to call filterByYear when i change the year?
[answer myself] the year was string instead number
how can i update the child component BarChart to update the information?
thank you!

jqgrid use in Django template: Reverse for 'item-jqgrid-entity1'

Trying to revive a Django app that was working 2014-2015 then was turned off for almost 3 years and now is not willing to cooperate.
Mac OS X el Capitan 10.11.6
Python 3.6 (also tried 3.4)
Django 1.8.3
In short, how does notation (in template) {% url 'item-jqgrid-entity1' pk=original.id %} connects to django models Item and Entity1 WITHOUT having item-jqgrid-entity1 listed in url.py ? I am getting
Reverse for 'item-jqgrid-entity1' with arguments '()' and
keyword arguments '{'pk': 123}' not found. 0 pattern(s) tried: []
and it used to work somehow. If I introduce matching URL in urls.py, it works, but I want to know how it was working without it.
For a given model (Item) the default template change_form.html was overriden. The custom one goes like this:
{% extends "admin/change_form.html" %}
{% load admin_urls %}
.
.
var searchable_columns = {
alteration_type: {
searchoptions: {
dataUrl: '{% url 'item-jqgrid-entity1' pk=original.id %}'
}
},
disease: {
searchoptions: {
dataUrl: '{% url 'item-jqgrid-entity2' pk=original.id %}'
}
},
}
.
.
$(document).ready( function () {
$("#table_{{ original.id }}").jqGrid({
autowidth: true,
height: 300,
hidegrid: false,
// double click handler
ondblClickRow: function(rowid, iRow, iCol, e) {
// rowid is object ID i want to edit
// mimics showRelatedObjectPopup()
// in django's RelatedObjectLookups.js
href = '{% url 'admin:some real url here' %}' + rowid + '/?_to_field=id&_popup=1';
$('div.alert').remove();
var win = window.open(href,
'id_drug',
'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;
},
// #25: workflow: marking edited rows
gridComplete: function () {
for (var i = 0; i < rowsToColor.length; i++) {
$("#" + rowsToColor[i]).find("td").css("background-color", "#dff0d8");
$("#" + rowsToColor[i]).find("td").css("color", "#468847");
}
// this will overwrite green ones, too.
for (var i = 0; i < incompleteRowsToColor.length; i++) {
$("#" + incompleteRowsToColor[i]).find("td").css("background-color", "#fcf8e3");
$("#" + incompleteRowsToColor[i]).find("td").css("color", "#b94a48");
}
// this will overwrite green and yellow ones, too.
for (var i = 0; i < unworthyRowsToColor.length; i++) {
$("#" + unworthyRowsToColor[i]).find("td").css("background-color", "#f2dede");
$("#" + unworthyRowsToColor[i]).find("td").css("color", "#b94a48");
}
// commented lines are bold.
for (var i = 0; i < commentedRowsToBold.length; i++) {
$("#" + commentedRowsToBold[i]).find("td").css("font-weight", "bold");
}
},
datatype: "json",
colModel: [
{
label: 'Entity1',
name: 'entity1',
width: 45,
// search options
stype: 'select',
searchoptions: searchable_columns.entity1.searchoptions,
editable: true,
edittype: 'select',
editoptions: {
dataUrl: '{% url 'editdata-AllEntity1' %}',
},
},
{
label: 'Entity2',
name: 'entity2',
width: 75,
// search options
stype: 'select',
searchoptions: searchable_columns.entity2.searchoptions,
editable: true,
edittype: 'select',
editoptions: {
dataUrl: '{% url 'editdata-allEntity2' %}',
},
],
viewrecords: true, // show the current page, data rang and total records on the toolbar
caption: "{{ original.pk }}: {{ original }}",
pager: "#tablePager_{{ original.id }}",
}
});
$('#table_{{ original.id }}').jqGrid('filterToolbar');
$('#table_{{ original.id }}').navGrid("#tablePager_{{ original.id }}", {
search: false, // show search button on the toolbar
add: false,
edit: false,
del: false,
refresh: true, position: "left", cloneToTop: true
},

Algolia - Search with a condition to look into an array of string

I am using rails and algolia gem with mongoid datastore.
I am sending data to algolia for a model Question. One of the doc example in Algolia system is
objectID: 5691e056410213a381000000
text: "what is #cool about your name Mr. John? #name #cool"
asked_to: ["565571704102139759000000", "i7683yiq7r8998778346q686", "kjgusa67g87y8e7qtwe87qwe898989"]
asked_by: "564a9b804102132465000000"
created_at: "2016-01-10T04:38:46.201Z"
card_url: "http://localhost:3000/cards/5691e056410213a381000000"
answerers: []
has_answer: false
requestor_count: 0
status: "active"
popularity_point: 0
created_at_i: 1452400726
_tags: ["cool", "name"]
I want to find all those documents, where it meets these two conditions:
1) text contains your name
2) asked_to contains i7683yiq7r8998778346q686
I am using Twitter's typeahead javascript library. And my UI's javascript to implement algolia search is as follows:
<input class="typeahead ui-widget form-control input-md search-box tt-input" id="typeahead-algolia" placeholder="Search questions" spellcheck="false" type="text" autocomplete="off" dir="auto" style="position: relative; vertical-align: top;">
$(document).on('ready page:load', function () {
var client = algoliasearch("APPLICATION_ID", "SEARCH_KEY");
var index = client.initIndex('Question');
$('#typeahead-algolia').typeahead(
{
hint: false,
highlight: true,
minLength: 1
},
{
source: index.ttAdapter({hitsPerPage: 10}),
displayKey: 'text'
}
).on('keyup', this, function (event) {
if (event.keyCode == 13) {
$('#typeahead-algolia').typeahead('close');
window.location.href = "/?keyword="+encodeURIComponent($('#typeahead-algolia').val());
}
});
$('.typeahead').bind('typeahead:select', function(ev, suggestion) {
window.location.href = suggestion.card_url;
});
});
So my question is:
This code works perfectly. But how to add condition for asked_to contains i7683yiq7r8998778346q686 in above javascript to filter out result.
You can use a facet filter on the asked_to attribute in your query.
You first need to declare the attribute asked_to as an attribute for faceting in your index settings and then pass asked_to:i7683yiq7r8998778346q686 as a facet filter in your query via the facetFiltersquery parameter.
When your index settings are changed, you can change your source to add the facetFilters parameter:
$('#typeahead-algolia').typeahead(
{
hint: false,
highlight: true,
minLength: 1
},
{
source: index.ttAdapter({hitsPerPage: 10, facetFilters: "asked_to:i7683yiq7r8998778346q686"}),
displayKey: 'text'
}
).on('keyup', this, function (event) {
if (event.keyCode == 13) {
$('#typeahead-algolia').typeahead('close');
window.location.href = "/?keyword="+encodeURIComponent($('#typeahead-algolia').val());
}
});

newbie mistake? JSON and Ember

new here to ember, and very much trying to learn - and learn where I'm going wrong.
I'm being fed json that looks like this:
"status": "success",
"data": {
"groups": [
{
"id": 2,
"name": "Test1234",
"kind": "Happy",
"parent_group_id": 1,
"children_count": {
"boy": 10,
"girl": 4,
"pets": 2
},
"is_top_level": true
},
The path to get this info would be /api/groups/top.
I have a (what I believe would be) simple app.js:
App = Ember.Application.create();
App.Router.map(function() {
this.route("login", {path: "/"});
this.route("groups");
this.resource('about');
});
App.GroupsRoute = Ember.Route.extend({
model: function() {
return App.Group.find('top');
}
});
App.LoginController = Ember.Controller.extend({
actions: {
login: function(username, password){
jQuery.ajax({
url: "/api/auth",
type: 'post',
data: JSON.stringify( { "username": "user", "password": "pass" } ),
contentType: 'application/json',
dataType: 'json',
async: false,
success: function(result) {
if (result.status === 'success') {
user = result.data.user;
App.User.id = user.id;
App.User.name = user.name;
App.User.isAuthenticated = true;
App.User.displayUnits = "F";
} else {
//debugger;
throw "The! username and/or password you have entered is incorrect, please try again ";
return false;
}
},
error: function(xhr, status, errorOut) {
throw "The? username and/or password you have entered is incorrect, please try again ";
return false;
}
});
if (App.User.isAuthenticated)
this.transitionToRoute('groups');
}}
});
App.RESTAdapter = RL.RESTAdapter.create({
host: 'http://localhost:3000',
namespace: 'api/'
});
App.Client = RL.Client.create({
adapter: App.RESTAdapter
});
App.User = RL.Model.extend({
username: RL.attr('string'),
id: RL.attr('string'),
isAuthenticated: RL.attr('boolean'),
});
App.Group = RL.Model.extend({
id: RL.attr('string'),
name: RL.attr('string'),
kind: RL.attr('string')
});
App.RESTAdapter = RL.RESTAdapter.create({
defaultData: { cookie: "data"}
});
I'm trying to display each "group" in my template. For example {{#each groups}} {{name}} {{/each}}, but no luck - I can see the JSON data in the response in inspector, and no errors - but still, nothing coming trough.
Any help?
Thanks!
Ptep
edit - template:
<script type="text/x-handlebars">
{{outlet}}
</script>
<script type="text/x-handlebars" id="groups">
<h3>Hello,
{{#each groups}}
{{name}}! <br>
{{kind}}, {{id}}
{{/each}}
</h3>
</script>
The array itself would be the context of your template, so you would either use
{{#each}}{{name}}{{/each}}
or
{{#each model}}{{name}}{{/each}}
or
{{#each controller}}{{name}}{{/each}}
or
{{#each item in controller}}{{item.name}}{{/each}}

How to parse nested arrays in a model in emberjs

I'm having trouble figuring out how to parse some json data from our backend server.
To start of, here's the data it returns:
{
"newsitem": {
"id": "1",
"title": "Some title",
"images": [
"IMG_0147.JPG",
"desert1.jpg"
],
"videos": [
"AEOpX8tmiUI",
"kxopViU98Xo"
]
}
}
I'm trying to parse this in my model:
App.Newsitem = DS.Model.extend({
title: DS.attr('string'),
images: DS.attr('array'),
videos: DS.attr('array')
});
But this give me an error that 'array' is not supported. How should I go with parsing this data and how should I print out the values of images and videos in the DOM through a handlebars template? I'm looking for a best-practise answer.
A lot of credits to nerdyworm on the #emberjs channel for the answer: you have to create your own serialize/deserialize methods for your new data type like this:
DS.JSONTransforms.array = {
serialize: function(jsonData) {
return Ember.typeOf(jsonData) == 'array' ? jsonData : [];
},
deserialize: function(externalData) {
return Ember.typeOf(externalData) == 'array' ? externalData : [];
}
}
Then in your handlebars template you can do:
<script type="text/x-handlebars" data-template-name="newsitem">
<div class="detail">
{{#each image in images}}
{{image}}<br/>
{{/each}}
</div>
</script>