Related
My app displays the total posts count, initially according to the server's response.
However, these posts can be filtered and I need to get the post count dynamically according to the filtering result.
inputFilter:function() {
var vm = this;
return vm.posts.filter((post) => {
var vmPosts = post.title.match(searchValue);
var countFilteredPostsDinammicaly = vmPosts.count(); //??????
return vmPosts;
});
}
Thanks.
You can make a computed property which will return you a filtered array on basis of the query/filters applied.
Another computed property will return you the length of the filtered array i.e filtered post count to show on the DOM.
new Vue({
el: '#app',
data: {
posts: [
{ title: 'apple is best fruit' },
{ title: 'orange is 2020 best fruit' },
{ title: 'apples are sweeter than oranges in 2020' }
],
query: ''
},
computed: {
getFilteredPosts () {
return this.posts.filter(post => post.title.includes(this.query))
},
getFilteredPostsCount () {
return this.getFilteredPosts.length
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input placeholder="search for `apple`" v-model="query"/>
<br/><br/>
Filtered posts count: {{ getFilteredPostsCount }}
<br/><br/>
Filtered posts:
<li v-for="(post, i) in getFilteredPosts" :key="i">
{{ post.title }}
</li>
</div>
I use HighChart library in the Segment, my segment have 2 tab DASHBOARD and NEW, my Chart in the DASHBOARD tab. First run: My Chart run, but i click to New tab and come back DASHBOARD tab => My chart not run ?
[sorry, i'm not good english]
-- My code html:
<div class="segment-chart">
<ion-segment [(ngModel)]="pet">
<ion-segment-button value="dashboard" (ionSelect)="selectedFriends()">
DASHBOARD
</ion-segment-button>
<ion-segment-button value="new">
NEW
</ion-segment-button>
</ion-segment>
</div>
<div [ngSwitch]="pet">
<div class="chart" *ngSwitchCase="'dashboard'">
<!--View Chart-->
<div #chart>
<chart type="StockChart" [options]="options"></chart>
</div>
</div>
<ul *ngSwitchCase="'new'" style="list-style-type:none" class="div-new-body">
<li class="div-new-li" *ngFor="let new of lsNews">
<div class="div-new-detail">
<div class="div-new-title">
{{new.date}}
</div>
<div class="div-new-content">
{{new.title}}
</div>
</div>
<div class="div-new-nav">></div>
</li>
</ul>
</div>
My code file ts:
export class ChartPage implements AfterViewInit, OnDestroy {
private _chart: any;
lastData: any
lstData: any = []
pet : any
lsNews : any = []
opts : any;
#ViewChild('chart') public chartEl: ElementRef;
//chartOption: any
// Destroy Chart
ngOnDestroy(): void {
// throw new Error("Method not implemented.");
console.log("OnDestroy run")
var chart = this._chart
chart.destroy();
}
// option Chart
ngAfterViewInit() {
if (this.chartEl && this.chartEl.nativeElement) {
this.opts.chart = {
// type: 'area',
renderTo: this.chartEl.nativeElement,
backgroundColor: {
linearGradient: [0, 0, 500, 500],
stops: [
[0, '#3d4d64'],
[1, '#3d4d64']
]
},
height: '90%',
spacingBottom: 15,
spacingTop: 10,
spacingLeft: 10,
spacingRight: 10,
};
console.log('chart create ss')
this._chart = new Highcharts.StockChart(this.opts);
}
}
constructor(public navCtrl: NavController, public navParams: NavParams, public service: Service) {
const me = this;
this.pet= 'dashboard';
setInterval(function () {
if (me._chart) {
me._chart['series'][0].addPoint([
(new Date()).getTime(), // gia tri truc x
//5// gia tri truc y
me.getData()
],
true,
true);
}
}, 3000);
this.opts = {
credits: {
enabled: false
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
labels: {
style: {
color: '#705f43' // color time
}
},
lineColor: '#705f43' // 2 line cuoi mau trang
},
yAxis: {
gridLineColor: '#705f43', //line gach ngang
labels: {
style: {
color: '#fff'
}
},
lineColor: '#ff0000',
minorGridLineColor: '#ff0000',
tickColor: '#fff',
tickWidth: 1,
title: {
style: {
color: '#ff0000'
}
}
},
navigator: {
enabled: false
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 0,
},
series: [{
name: 'Random data',
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -50; i <= 0; i += 1) {
data.push([
time + i * 1000,
Math.round(Math.random() * 100)
]);
}
return data;
}()),
zones: [{
color: '#f8ad40'
}]
}]
};
//end contructor
}
In case you have not been able to resolve this issue, I had the same issue using ion-segment and I was able to resolve it when I replaced ngSwitch with the [hidden] property.
The problem is that the canvas only get rendered once. The canvas is also lost once you switch between your segments, the only solution is to hide you segment when switching between segments
Edit your HTML code to the one below and you should be okay
<div class="segment-chart">
<ion-segment [(ngModel)]="pet">
<ion-segment-button value="dashboard" (ionSelect)="selectedFriends()">
DASHBOARD
</ion-segment-button>
<ion-segment-button value="new">
NEW
</ion-segment-button>
</ion-segment>
</div>
<div >
<div class="chart" [hidden] = "pet != 'dashboard'">
<!--View Chart-->
<div #chart>
<chart type="StockChart" [options]="options"></chart>
</div>
</div>
<ul [hidden] = "pet != 'new'" style="list-style-type:none" class="div-new-body">
<li class="div-new-li" *ngFor="let new of lsNews">
<div class="div-new-detail">
<div class="div-new-title">
{{new.date}}
</div>
<div class="div-new-content">
{{new.title}}
</div>
</div>
<div class="div-new-nav">></div>
</li>
</ul>
</div>
That should solve the issue.
I've been working with vue js 1.27 on a project and I need to be able to sort a list by numeric values, Alphabetic and reverse order.
I've been trying this all day with not really much progress.
I've left some of my previous code in my code sample to let you know what I've already attempted.
{% extends 'base.html.twig' %}
{% block body %}
<div id="wrap">
<h2>Select a category</h2>
<ul id="categorySelect">
<li v-for="cat in categories | orderBy reverse" #click="selectCategory(cat)" class="${cat.selectedCategory == category ? 'selected' : ''}">${cat.title}</li>
</ul>
</div>
{% endblock %}
{% block javascripts %}
<script type="text/javascript">
Vue.config.delimiters = ['${', '}'];
new Vue({
el: '#wrap',
data: {
//reverse: -1,
wasClicked: true,
selectedCategory: null,
categories: [{
title: 'ALL',
category: null
},
{
title: 'CATE',
category: 'sport'
},
{
title: 'DOG',
category: 'sport'
},
{
title: 'SPEED',
category: 'sport'
},
{
title: 'CAT',
category: 'sport'
},
{
title: 'SPORT',
category: 'sport'
},
{
title: 'ART',
category: 'sport'
},
{
title: 'PEOPLE',
category: 'people'
},
{
title: 'CAR',
category: 'car'
}]
},
filters: {
categoryFilter: function (infoBlocs) {
return this.wasClicked ? this.categories : {};
},
caseFilter: function () {
if (this.wasClicked) {
return this.reverseArray();
}
return this.alphaSortByKey(this.categories, 'category');
},
reverse: function(value) {
// slice to make a copy of array, then reverse the copy
return value.slice().reverse();
}
},
methods: {
selectCategory: function(category) {
//this.wasClicked =! this.wasClicked;
//this.categories = this.alphaSortByKey(this.categories, 'category');
// if (this.reverse) {
// this.categories = this.alphaSortByKey(this.categories, 'category');
// }
// else {
// this.categories = this.reverseArray();
// }
if (this.reverse) {
this.categories = this.alphaSortByKey(this.categories, 'category');
this.reverse = false;
}
else {
this.categories = this.reverseArray();
//this.reverse = true;
}
},
alphaSortByKey: function (arr, key) {
arr.sort(function (a, b) {
if (a[key] < b[key])
return -1;
if (a[key] > b[key])
return 1;
return 0;
});
return arr;
},
reverseArray: function () {
return this.categories.reverse();
},
changeOrder: function (event) {
var self = this;
self.reverse = self.reverse * -1
var newItems = self.categories.slice().sort(function (a, b) {
var result;
if (a.name < b.name) {
result = 1
}
else if (a.name > b.name) {
result = -1
}
else {
result = 0
}
return result * self.reverse
})
newItems.forEach(function (item, index) {
item.position = index;
});
this.categories = newItems;
}
}
});
</script>
{% endblock %}
Here is a fiddle with working functionality to sort and reverse the order of your array. For reverse I just used the built in reverse() Javascript function. For the alphanumeric sort I borrowed the solution from this answer: https://stackoverflow.com/a/4340339/6913895
https://jsfiddle.net/n1tbmgo9/
Html:
<div id="wrap">
<h2>Select a category</h2>
<button #click="sort">
Sort alphanumeric
</button>
<button #click="reverse">
Reverse list
</button>
<ul id="categorySelect">
<li v-for="cat in categories">${cat.title}</li>
</ul>
</div>
Javascript:
Vue.config.delimiters = ['${', '}'];
new Vue({
el: '#wrap',
data: {
selectedCategory: null,
categories: [{
title: 'ALL',
category: null
},
{
title: 'CATE',
category: 'sport'
},
{
title: 'DOG',
category: 'sport'
},
{
title: 'SPEED',
category: 'sport'
},
{
title: 'CAT',
category: 'sport'
},
{
title: 'SPORT',
category: 'sport'
},
{
title: 'ART',
category: 'sport'
},
{
title: 'PEOPLE',
category: 'people'
},
{
title: 'CAR',
category: 'car'
}]
},
methods: {
sort: function () {
this.categories.sort(this.sortAlphaNum);
},
reverse: function () {
this.categories.reverse();
},
sortAlphaNum: function (a,b) {
var reA = /[^a-zA-Z]/g;
var reN = /[^0-9]/g;
var aA = a.title.replace(reA, "");
var bA = b.title.replace(reA, "");
if(aA === bA) {
var aN = parseInt(a.title.replace(reN, ""), 10);
var bN = parseInt(b.title.replace(reN, ""), 10);
return aN === bN ? 0 : aN > bN ? 1 : -1;
} else {
return aA > bA ? 1 : -1;
}
}
}
});
The built in reverse() function is straightforward so I will elaborate on the sortAlphaNum() sort function. That function is passed into the sort() function and must return either 1, 0, or -1 to indicate if the objects passed in should be moved in a particular direction in the array.
The variables reA and reN are regexes to identify alphabetic and numeric characters, respectively.
First the function removes all alphabet characters from the titles of the two objects passed in and compares them for equality.
var aA = a.title.replace(reA, ""); and
var bA = b.title.replace(reA, "");
If they are not equal then it means we have alphabet characters (as opposed to just numeric input) and we can sort them accordingly.
return aA > bA ? 1 : -1;
If the titles with alphabet characters stripped are equal (if(aA === bA)) then we remove numeric digits from the object titles (leaving non-numeric characters).
var aN = parseInt(a.title.replace(reN, ""), 10);
var bN = parseInt(b.title.replace(reN, ""), 10);
Then we compare the resulting variables and return the appropriate sorting value (1, 0, -1).
return aN === bN ? 0 : aN > bN ? 1 : -1;
create a computed property where you manually sort it and then loop for that instead the data prop
There is my List Component implementation with client-side order implementation:
<template>
<div>
<table class="table table-bordered" v-if="data.length">
<thead>
<tr>
<th v-for="(colValue, colKey) in cols" :key="colKey">
<a #click="sort(colKey)" href="javascript:void(0)">
{{colValue}}
<icon :name="(sortColumn === colKey) ? (sortAsc ? 'sort-down' : 'sort-up') : 'sort'"></icon>
</a>
</th>
</tr>
</thead>
<tbody>
<tr v-for="row in data" :key="row.id">
<td v-for="(colValue, colKey) in cols" :key="row.id + colKey">{{row[colKey]}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import _ from 'lodash';
import apiServer from '#/utils/apiServer'; //
export default {
name: 'List',
data() {
return {
data: [],
sortColumn: '',
sortAsc: true
};
},
props: {
cols: {
type: Object,
required: true
},
apiEndpoint: {
type: String,
required: true
}
}
created() {
this.fetchData();
},
watch: {
'$route': 'fetchData'
},
methods: {
async fetchData() {
const response = await apiServer.get(this.apiEndpoint);
this.data = response.data;
},
sort(colKey) {
this.data = _.sortBy(this.data, [colKey]);
if (this.sortColumn === colKey) {
if (!this.sortAsc) {
this.data = _.reverse(this.data);
}
this.sortAsc = !this.sortAsc;
} else {
this.sortAsc = false;
}
this.sortColumn = colKey;
}
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>
Usage example
<template>
<div>
<h1>Orders</h1>
<List :cols="cols" api-endpoint="/orders" title="Orders" />
</div>
</template>
<script>
import List from '#/components/List.vue';
export default {
name: 'OrderList',
components: { List },
data() {
return {
cols: {
id: 'Id',
title: 'Title',
created_at: 'Created at'
}
};
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>
I'm currently working on an interactive chart which should calculate potential risk-factors of commercial project. I've been using Baidu ECharts for this, and got the graph working visually, but can't get the graph to update when data changes.
The data comes from an external questionnaire, which uses radiobuttons for the values and a checkbox to turn the whole set on and off.
<input type="checkbox" id="GPEbool" value="true"> Example Question 1</h4>
<form action="">
<input type="radio" id="polishedness" value="1"> Idea<br>
<input type="radio" id="polishedness" value="1"> Concept<br>
<input type="radio" id="polishedness" value="2"> Mockup<br>
<input type="radio" id="polishedness" value="5"> Prototype<br>
<input type="radio" id="polishedness" value="7"> Playable<br>
<input type="radio" id="polishedness" value="15"> Polish<br>
<input type="radio" id="polishedness" value="30"> Finished<br>
</form>
Now, the problem is getting the data into the graph. It gets the initially selected value right (when adding "checked" to one of them), but won't update after that.
data: [{ value: $('input[name=polishedness]:checked').val(), name: 'Design'}]
I've tried calling the refresh function whenever something changes, but it'll return refresh is not a function. I'm really at loss, and the Chinese documentation doesn't help me much :)
Any suggestions? Thanks in advance!
You have to call chartInstance.setOption() again with your new data.
I give you a small example:
// eChart is the chart instance!
echart.setOption({
// .... some configuration
series: [
{
type: "line",
name: "test",
data: [1,2,3,4,5,6]
}
]
})
After you changed the value of your select box, you have to catch that event, change the value of the configuration object and call chartInstance.setOption() again.
Therefore, it is sometimes advisable to save your complete configuration object and store your changes there.
You can use resize() method, for example
window.chartRadar = echarts.init(document.getElementById('echartId'));
window.chartRadar.setOption({
title: {
text: 'radar echart'
},
tooltip: {},
legend: {
data: ['data1', 'data2']
},
radar: {
// shape: 'circle',
name: {
textStyle: {
color: '#fff',
backgroundColor: '#999',
borderRadius: 3,
padding: [3, 5]
}
},
indicator: [
{ name: 'sales', max: 6500},
{ name: 'Administration', max: 16000},
{ name: 'Information Techology', max: 30000},
{ name: 'Customer Support', max: 38000},
{ name: 'Development', max: 52000},
{ name: 'Marketing', max: 25000}
]
},
series: [{
name: 'Budget vs spending',
type: 'radar',
// areaStyle: {normal: {}},
data : [
{
value : [4300, 10000, 28000, 35000, 50000, 19000],
name : 'data1'
},
{
value : [5000, 14000, 28000, 31000, 42000, 21000],
name : 'data2'
}
]
}]
});
Once you alreay make you echart you cloud use the method "resize()" for redraw the echar for example
window.chartRadar.resize();
If you are using Angular ,
You can also use the [merge] option to have the Chart responding for the value changes,
<div echarts [options]="initialValue" [merge]= "dynamicData" class="demo-chart"></div>
Reference : https://github.com/xieziyu/ngx-echarts#api
In your Module assign Initial Value as below,
initialValue: EChartOption = {
xAxis: {
type: 'time',
splitNumber : 20
},
yAxis: {
type: 'value',
name : '$',
nameLocation: 'middle'
},
series: [{
data : [],
type: 'line'
}]
}
and set the Dynamic value based on your data, Also initialize "this.dynamicData" before making the api calls to the external service
formDataforChart(backTestTrades) {
let i = 0;
for(let backTestTrade of backTestTrades){
let profitAndTime = [];
profitAndTime.push(backTestTrade.exitTime);
profitAndTime.push(backTestTrade.profitOrLoss);
this.eChartDataSeries.push(profitAndTime);
}
let data = {
data : this.eChartDataSeries,
type : 'bar'
};
this.dynamicData=this.initialValue;
this.dynamicData.series = [];
// Applying my dynamic data here
this.dynamicData.series.push(data);
}
I don't understand why, but Django has ceased including the csrf cookie in responses. I have the middleware enabled, have tried using RequestContext and am using render. I have even tried using the csrf_protect and requires_csrf_token decorators.
I am working on a dev server right now, and I can print the context after I use RequestContext, and it seems to include a csrf_token.
But when I look at the actual headers using Chrome's inspect element, the csrf_token isn't there, also when I use the console and type in "document.cookie" that does not have the csrf token.
HELP!
Here's an example view
#requires_csrf_token
def index(request):
context = RequestContext(request, {'foo':'bar'})
print context
return render(request, 'index.html', context)
The CSRF token seems to be in the context:
{u'csrf_token': <django.utils.functional.__proxy__ object at 0x1025ab990>}, ...
But it fails to make its way through...
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Cookie:__utma=96992031.468590559.1369255550.1369255550.1369255550.1; __utmb=96992031.17.10.1369255550; __utmc=96992031; __utmz=96992031.1369255550.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Host:127.0.0.1:8000
Referer:http://127.0.0.1:8000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31
UPDATE: Here is the template I'm using:
{% extends "base.html" %}
{% block hello %}
Basic Stock Event Charts
{% endblock %}
{% block content %}
<div id="leftsidebar">
<p>Use this tool to graph a time series data for a security. You can graph a security and
four other features such as volume, call option volume, or implied volatility. The tool will
zoom in on the date of interest to show the target audience the changes in the selected
vaiables preceeding the event. Because of large movement in variables before the announcement,
it may be helpful to use the minimum and maximum tools to zoom in on smaller movements ahead
of the event. </p>
<div class="ui-widget inline">
<label for="securities">1. Type in a ticker symbol</label>
<input id="securities">
</div>
<div class="inline"><input type="button" id="reload" value="Reset" class="hide" /></div>
<label for="datepicker">2. Pick your event date of interest.</label>
<input type="text" id="datepicker" disabled />
<label>3. Choose other series to graph.</label>
<p><strong>Primary Axis</strong></p>
Left Axis: <select id="series1" class="selectpicker span2" disabled><option value=""></option></select>
<div id="series1minmax" class="hide">
Min <input type="text" id="min1" class="input-mini" />
Max <input type="text" id="max1" class="input-mini" />
</div><input type="button" id="addaxes1" value="Graph" class="hide" />
<input type="button" id="removeaxes1" value="Remove" class="hide" /><br />
<br/>Right Axis: <select id="series2" class="selectpicker span2" disabled><option value=""></option>></select>
<div id="series2minmax" class="hide">
Min <input type="text" id="min2" class="input-mini" />
Max <input type="text" id="max2" class="input-mini" />
</div><input type="button" id="addaxes2" value="Graph" class="hide" />
<input type="button" id="removeaxes2" value="Remove" class="hide" /><br />
<input type="button" id="addextraaxis" value="Add Additional Axis" disabled/><br />
<div id="additional" class="hide">
<p><strong>Additional Axis</strong></p>
Left Axis: <select id="series3" class="selectpicker span2" disabled><option value=""></option></select>
<div id="series3minmax" class="hide">
Min <input type="text" id="min3" class="input-mini" />
Max <input type="text" id="max3" class="input-mini" />
</div><input type="button" id="addaxes3" value="Graph" class="hide" />
<input type="button" id="removeaxes3" value="Remove" class="hide" /><br />
<br/>Right Axis: <select id="series4" class="selectpicker span2" disabled><option value=""></option>></select>
<div id="series4minmax" class="hide">
Min <input type="text" id="min4" class="input-mini" />
Max <input type="text" id="max4" class="input-mini" />
</div><input type="button" id="addaxes4" value="Graph" class="hide" />
<input type="button" id="removeaxes4" value="Remove" class="hide" /><br />
</div>
</div>
<div id="rightsidebar">
<div id="container" class="hide"></div>
</div>
</div>
<script src="http://code.highcharts.com/stock/highstock.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<script src="http://code.highcharts.com/stock/highcharts-more.js"></script>
<script>
$(function() {
$("#removefromchart").click(function() {
var conceptName = $('#savedseries').find(":selected").remove();
});
$("#reload").click(function() {
location.reload();
})
$("#addextraaxis").click(function() {
$("#additional").removeClass("hide");
this.disabled = true
$("#addextraaxis").addClass("hide");
var chart = $("#container").highcharts();
chart.setSize(null, 650);
})
});
$(function() {
$("#series1").change(function() {
$("#addaxes1").removeClass("hide");
});
$("#series2").change(function() {
$("#addaxes2").removeClass("hide");
});
$("#series3").change(function() {
$("#addaxes3").removeClass("hide");
});
$("#series4").change(function() {
$("#addaxes4").removeClass("hide");
});
});
$(function() {
function setExtreme(isMin, axis, value) {
console.log("fired");
var chart = $('#container').highcharts();
if (isMin) {
console.log(value + " " + chart.yAxis[axis].getExtremes()["max"])
chart.yAxis[axis].setExtremes(value, chart.yAxis[axis].getExtremes()["max"]);
} else {
console.log(value + " " + chart.yAxis[axis].getExtremes()["min"])
chart.yAxis[axis].setExtremes(chart.yAxis[axis].getExtremes()["min"], value);
}
console.log(value);
}
function getAxisNumber(series) {
var indicies = {}
$.each(chart.yAxis, function(index, element) {
indicies[element.options.id] = index;
console.log(element.options.id);
});
return indicies[series]
}
$("#max1").change(function() {setExtreme(0, getAxisNumber("#series1"), this.value)});
$("#min1").change(function() {setExtreme(1, getAxisNumber("#series1"), this.value)});
$("#max2").change(function() {setExtreme(0, getAxisNumber("#series2"), this.value)});
$("#min2").change(function() {setExtreme(1, getAxisNumber("#series2"), this.value)});
$("#max3").change(function() {setExtreme(0, getAxisNumber("#series3"), this.value)});
$("#min3").change(function() {setExtreme(1, getAxisNumber("#series3"), this.value)});
$("#max4").change(function() {setExtreme(0, getAxisNumber("#series4"), this.value)});
$("#min4").change(function() {setExtreme(1, getAxisNumber("#series4"), this.value)});
});
$(function()
{
$("#removefromchart").click(function()
{
var conceptName = $('#savedseries').find(":selected").remove();
});
});
$(function() {
function addPlotLine(ts) {
var chart = $('#container').highcharts();
chart.xAxis[0].addPlotBand({
from: ts,
to: ((ts + 86400000) * 365),
color: 'rgba(68, 170, 213, 0.2)',
id: 'tsband'
});
chart.xAxis[0].addPlotLine({
value: ts,
color: 'rgb(255, 0, 0)',
width: 1,
id: 'tsline'
});
chart.xAxis[0].setExtremes(ts - (86400000 * 30), ts + 86400000)
}
function removeEventIfExists() {
var chart = $("#container").highcharts()
chart.xAxis[0].removePlotBand("tsband");
chart.xAxis[0].removePlotLine("tsline");
}
$("#datepicker").datepicker({
showButtonPanel: true, /*added by oussama*/
changeMonth: true, /*added by oussama*/
changeYear: true, /*added by oussama*/
dateFormat: 'yy-mm-dd',
onSelect: function (dateText, inst) {
utcDate = Date.UTC(dateText.split("-")[0], dateText.split("-")[1] - 1, dateText.split("-")[2]);
removeEventIfExists();
addPlotLine(utcDate);
$("#series1").removeAttr("disabled");
$("#series2").removeAttr("disabled");
$("#series3").removeAttr("disabled");
$("#series4").removeAttr("disabled");
$("#addextraaxis").removeAttr("disabled");
var ticker = $("#securities").val();
var date = $("#datepicker").val();
chart.setTitle({text: ticker + " around " + date});
}
});
});
$(function() {
function createChart() {
var chart = $('#container').highcharts();
var options = {chart: {
renderTo: 'container',
height: 450,
},
events: {
load: function(event) {
this.setExtremes();
}
},
rangeSelector: {
enabled: false,
},
exporting: {
enabled: false,
},
navigator: {
enabled: true,
series: { id: 'navigator' },
},
yAxis: [{
title: {
text: 'Price'
},
height: 150,
}],
},
chart = new Highcharts.StockChart(options);
return chart;
}
$("#securities").autocomplete({
source: "/api/get_securities/",
minLength: 1,
select: function(event, ui) {
var ticker = ui.item.label;
getSeries(ticker);
chart = createChart();
getTimeSeriesData(ticker + "|PX_LAST", 0);
$('#container').show();
$('#datepicker').removeAttr("disabled");
$('#reload').removeClass("hide");
chart.setTitle({text: ticker});
this.disabled = 'disabled';
},
});
});
$(function() {
function removeAxes(id) {
var chart = $('#container').highcharts();
chart.get(id).remove();
}
$("#removeaxes1").click(function() {
console.log("removeaxes1 clicked");
removeAxes("#series1");
$("#removeaxes1").addClass("hide");
$("#series1minmax").addClass("hide");
$("#series1minmax").removeClass("inline");
$("#series1").val("");
$("#min1").val("");
$("#max1").val("");
$("#series1").removeAttr("disabled");
});
$("#removeaxes2").click(function() {
console.log("removeaxes2 clicked");
removeAxes("#series2");
$("#removeaxes2").addClass("hide");
$("#series2minmax").addClass("hide");
$("#series2minmax").removeClass("inline");
$("#series2").val("");
$("#min2").val("");
$("#max2").val("");
$("#series2").removeAttr("disabled");
});
$("#removeaxes3").click(function() {
console.log("removeaxes3 clicked");
removeAxes("#series3");
$("#removeaxes3").addClass("hide");
$("#series3minmax").addClass("hide");
$("#series3minmax").removeClass("inline");
$("#series3").val("");
$("#min3").val("");
$("#max3").val("");
$("#series3").removeAttr("disabled");
});
$("#removeaxes4").click(function() {
console.log("removeaxes4 clicked");
removeAxes("#series4");
$("#removeaxes4").addClass("hide");
$("#series4minmax").addClass("hide");
$("#series4minmax").removeClass("inline");
$("#series4").val("");
$("#min4").val("");
$("#max4").val("");
$("#series4").removeAttr("disabled");
});
function addSeries(id, minMaxId, isOpposite, isAdditional) {
var chart = $('#container').highcharts();
indicies = {}
console.log('climlckedaddaxes');
var series = $(id).val()
var top = 210
if (isAdditional) top = 380
var options = {
title: {
text: series.split("|")[1]
},
top: top,
height: 150,
opposite: isOpposite,
id: id,
offset: -30
}
chart.addAxis(options)
$.each(chart.yAxis, function(index, element) {
indicies[element.options.id] = index;
console.log(element.options.id);
});
getTimeSeriesData(series, indicies[id]);
$(minMaxId).removeClass("hide")
$(minMaxId).addClass("inline")
}
$("#addaxes1").click(function() {
addSeries('#series1', "#series1minmax", false, false);
$("#addaxes1").addClass("hide")
$("#removeaxes1").removeClass("hide")
$("#series1").attr("disabled", "disabled")
});
$("#addaxes2").click(function() {
addSeries('#series2', "#series2minmax", true, false);
$("#addaxes2").addClass("hide")
$("#removeaxes2").removeClass("hide")
$("#series2").attr("disabled", "disabled")
});
$("#addaxes3").click(function() {
addSeries('#series3', "#series3minmax", false, true);
$("#addaxes3").addClass("hide")
$("#removeaxes3").removeClass("hide")
$("#series3").attr("disabled", "disabled")
});
$("#addaxes4").click(function() {
addSeries('#series4', "#series4minmax", true, true);
$("#addaxes4").addClass("hide")
$("#removeaxes4").removeClass("hide")
$("#series4").attr("disabled", "disabled")
});
})
$('#addtochart').click(function() {
var selectedValues = $('#seriesselector').val();
$.each(selectedValues, function(index, value) {
$('#savedseries').append($('<option>', {
value: value,
text: value,
selected: true,
}));
$('#seriesselector option[value="' + value +'"]').remove();
});
});
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function parseDate(inputdate, value) {
var date = inputdate;
var year = parseInt(date.split("-")[0]);
var month = parseInt(date.split("-")[1]) - 1;
var day = parseInt(date.split("-")[2]);
var outputdate = Date.UTC(year, month, day);
if (year == 2013 && month == 3) {
//console.log(inputdate, outputdate, value);
}
return outputdate;
};
function getTimeSeriesData(seriesName, axis) {
var csrftoken = getCookie('csrftoken');
console.log('csrftoken is :: ' + csrftoken);
$.ajax({ // create an AJAX call...
beforeSend: function(xhr, settings) {
var csrftoken = getCookie('csrftoken');
xhr.setRequestHeader("X-CSRFToken", csrftoken);
},
data: {'seriesName': seriesName }, // get the form data
type: 'POST',
url: '/api/get_time_series_data/',
success: function(response) { // on success..
console.log(response);
var series = {}
series['name'] = response[0]['series_name'];
series['data'] = []
$.each(response, function(index, value) {
series['data'][index] = [
parseDate(response[index]['date'], response[index]['value']),
parseFloat(response[index]['value'])
];
});
series['yAxis'] = axis
series['marker'] = {
enabled : true,
radius : 3
}
var chart = $('#container').highcharts();
chart.addSeries(series);
var nav = chart.get('navigator');
if (axis == 0) nav.setData(series['data']);
}
});
return false;
};
function getSeries(ticker) {
var csrftoken = getCookie('csrftoken');
$.ajax({ // create an AJAX call...
beforeSend: function(xhr, settings) {
var csrftoken = getCookie('csrftoken');
xhr.setRequestHeader("X-CSRFToken", csrftoken);
},
data: {'ticker': ticker }, // get the form data
type: 'POST',
url: '/api/get_series/',
success: function(response) { // on success..
$('#seriesselector').empty()
for (var i = 0; i < response.length; i++) {
if (response[i].value == 'PX_LAST') continue;
$('#series1').append($('<option>', {
value: ticker + "|" + response[i].value,
text: response[i].value
}));
$('#series2').append($('<option>', {
value: ticker + "|" + response[i].value,
text: response[i].value
}));
$('#series3').append($('<option>', {
value: ticker + "|" + response[i].value,
text: response[i].value
}));
$('#series4').append($('<option>', {
value: ticker + "|" + response[i].value,
text: response[i].value
}));
}
}
});
return false;
};
</script>
{% endblock %}
Turns out you need the
{% csrf_token %}
regardless of whether or not you are posting a html form. I was only doing AJAX requests, but Django won't include the token in the response header unless it sees it the template.