I have pie chart webpage (index.html) which is currently getting values from a static .js file.
The original content of the .js file for the pie chart is this:
$( document ).ready(function() {
var ctx110 = document.getElementById("chart110").getContext("2d");
var data110 = [
{
"value": 40,
"color": "#F25656",
"highlight": "#FD7A7A",
"label": "Critical"
},
{
"value": 63.2452,
"color": "#22BAA0",
"highlight": "#36E7C8",
"label": "Other"
},
{
"value": 0,
"color": "#F2CA4C",
"highlight": "#FBDB6E",
"label": "Warning"
}
];
var chart110 = new Chart(ctx110).Pie(data110,{
segmentShowStroke : true,
segmentStrokeColor : "#fff",
segmentStrokeWidth : 2,
animationSteps : 100,
animationEasing : "easeOutBounce",
animateRotate : true,
animateScale : false,
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>",
responsive: true
});
});
However, I need to make the values in the var data110 variable dynamic.
I have a php script that, when run, spits out the required value and my issue is, I'm having problems getting the pie chart to load after I incorporate the php script into the above code.
Here's my attempt (I'm completely new to web development, so please forgive my ineptitude here - i know it's very ugly):
$( document ).ready(function() {
var ctx110 = document.getElementById("chart110").getContext("2d");
function internal_loadXMLDoc1() {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("myDivAX1").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("POST","getnum.php?os-metrics",true);
xmlhttp.send();
}
var dskmetric = internal_loadXMLDoc1();
var data110 = [
{
"value": dskmetric,
"color": "#F25656",
"highlight": "#FD7A7A",
"label": "Critical"
},
{
"value": 63.2452,
"color": "#22BAA0",
"highlight": "#36E7C8",
"label": "Other"
},
{
"value": 0,
"color": "#F2CA4C",
"highlight": "#FBDB6E",
"label": "Warning"
}
];
var chart110 = new Chart(ctx110).Pie(data110,{
segmentShowStroke : true,
segmentStrokeColor : "#fff",
segmentStrokeWidth : 2,
animationSteps : 100,
animationEasing : "easeOutBounce",
animateRotate : true,
animateScale : false,
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>",
responsive: true
});
});
EDIT (based on #AL-zami advice):
$( document ).ready(function() {
var ctx110 = document.getElementById("chart110").getContext("2d");
function internal_loadXMLDoc1() {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
// Do your work here
var data110 = [
{
**"value": [this needs to be dynamic]**,
"color": "#F25656",
"highlight": "#FD7A7A",
"label": "Critical"
},
{
**"value": [this needs to be dynamic]**,
"color": "#22BAA0",
"highlight": "#36E7C8",
"label": "Other"
},
{
"value": 0,
"color": "#F2CA4C",
"highlight": "#FBDB6E",
"label": "Warning"
}
];
var chart110 = new Chart(ctx110).Pie(data110,{
segmentShowStroke : true,
segmentStrokeColor : "#fff",
segmentStrokeWidth : 2,
animationSteps : 100,
animationEasing : "easeOutBounce",
animateRotate : true,
animateScale : false,
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>",
responsive: true
});
}
}
xmlhttp.open("POST","getnum.php?os-metrics",true);
xmlhttp.send();
}
internal_loadXMLDoc1();
});
Here's the PHP script getnum.php:
<?php
$allargs = $_SERVER["argv"];
$argscou = $_SERVER["argc"];
if ( $argscou == 0 ) {
die();
} else {
$upatterns = var_export($allargs, true) ;
if (strpos($upatterns, '__') !== false) {
$type_val = explode("__", $allargs[0]);
} else {
$type_val = $allargs;
}
$compon1 = $type_val[0];
if ($compon1== "30day-expirations") {
$compon2 = $type_val[1];
echo '<p class="counter">' . "$compon2" . '</p>'. "\n";
} else if ( ($compon1 == "getnum.php") || ($compon1 == "os-disk-usage") ) {
$duvalue = "400";
echo "$duvalue";
file_put_contents('4filename.txt', $duvalue, FILE_APPEND);
}
}
?>
Your problem statement is not clear. Hard to determine what you are trying to accomplish. If I understand you correctly, your problem lies in you post request handler. XMLHttpRequest is a asynchronous request. Your rest of the code run to completion before the post request is resolved.
var dskmetric = internal_loadXMLDoc1();
The above statement doesn't return anything. Try to run you chart generation code inside the handler function.
var ctx110 = document.getElementById("chart110").getContext("2d");
function internal_loadXMLDoc1() {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
// Do your work here
}
}
xmlhttp.open("POST","getnum.php?os-metrics",true);
xmlhttp.send();
}
internal_loadXMLDoc1();
If you are not submitting any form try to change the request method to GET
You can use the following example:
<?php
$data = [
[
"value" => 'dskmetric',
"color" => "#F25656",
"highlight" => "#FD7A7A",
"label" => "Critical"
],
[
"value" => 63.2452,
"color" => "#22BAA0",
"highlight" => "#36E7C8",
"label" => "Other"
],
[
"value" => 0,
"color" => "#F2CA4C",
"highlight" => "#FBDB6E",
"label" => "Warning"
]
];
?>
<script type="application/json" id="j-data">
{ "data": <?php echo json_encode($data ?? []); ?>}
</script>
<script>
var data = JSON.parse($("#j-data")[0].innerHTML);
</script>
Related
I have a pie chart integration in Spotfire which works well when the data is in a simpler format in 'data' and 'columns'. The data binds to the chart properly (this is the kind of format i've seen in most demos).
However in other real-life usages in Spotfire, the JSON which is produced is differently formatted and ceases to draw a pie chart properly. I think it should be possible to adjust the script to bind to this data format, but i don't know how?
In my fiddle it is working with simpler data format, if commenting this out and uncommenting the other data the failed chart can be seen...
https://jsfiddle.net/paulsmithleadershipfactor/3k2gzuw0/
The full code is here also...
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9"/>
<title>JS Visualization Tester with Highcharts</title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script>
var chart; // Global chart object used to determine whether Highcharts has been intialized
var color = null;
var pie = null;
var svg = null;
var path = null;
function renderCore(sfdata)
{
if (resizing) {
return;
}
// Extract the columns
var columns = sfdata.columns;
columns.shift();
// Extract the data array section
var chartdata = sfdata.data;
// count the marked rows in the data set, needed later for marking rendering logic
var markedRows = 0;
for (var i = 0; i < chartdata.length; i++)
{
if (chartdata[i].hints.marked)
{
markedRows = markedRows + 1;
}
}
var width = window.innerWidth;
var height = window.innerHeight;
var radius = Math.min(width, height) / 2;
if ( !chart )
{
$('#js_chart').highcharts({
chart: {
plotBackgroundColor: '#f1f2f2',
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: 'Pie',
},
tooltip: {
formatter: function() {
var sliceIndex = this.point.index;
var sliceName = this.series.chart.axes[0].categories[sliceIndex];
return sliceName + ':' +
'<b>' + this.y + '</b>';
}
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
showInLegend: true,
depth: 35,
innerSize: 100,
dataLabels: {
enabled: true,
format: '{point.y:,.0f}'
}
}
},
legend: {
enabled: true,
labelFormatter: function() {
var legendIndex = this.index;
var legendName = this.series.chart.axes[0].categories[legendIndex];
return legendName;
}
},
xAxis: {
categories: columns
}
});
}
chart = $('#js_chart').highcharts();
for ( var nIndex = 0 ; nIndex < chartdata.length ; nIndex++ )
{
var row = chartdata[nIndex];
// Check for an existing chart data series with the current id
var series = chart.get ( row.items[0] );
var seriesData = [];
for (var c = 1; c < row.items.length; c++) {
seriesData.push(Number(row.items[c]));
}
if ( series != null )
{
// Update the existing series with the new data
series.update ( {
data: seriesData
}, false );
}
else
{
// Create a new series
chart.addSeries ( {
id: row.items[0],
name: row.items[0],
data: seriesData
}, false );
}
}
for ( nSeriesIndex = 0 ; nSeriesIndex < chart.series.length ; nSeriesIndex++ )
{
var series = chart.series[nSeriesIndex];
var found = false;
for ( nDataIndex = 0 ; nDataIndex < chartdata.length ; nDataIndex++ )
{
var row = chartdata[nDataIndex];
if ( series.name == row.items[0] )
{
found = true;
break;
}
}
if ( found != true )
{
series.remove ( false );
nSeriesIndex = 0;
}
}
chart.redraw ();
wait ( sfdata.wait, sfdata.static );
}
var resizing = false;
window.onresize = function (event) {
resizing = true;
if ($("#js_chart")) {
}
resizing = false;
}
</script>
</head>
<body>
<button style="position:absolute; z-index:99" type="button" onclick="call_renderCore()">Call renderCore</button>
<div id="js_chart"></div>
<script type="text/javascript">
function call_renderCore()
{
var sfdata =
{
"columns": ["Sales (Total)", "Marketing (Total)", "Development (Total)", "Customer Support (Total)", "IT (Total)", "Administration (Total)"],
/* comment out the 'columns' above and uncomment 'columns' below */
/* "columns": [
"count([lastcontact])",
"First([lastcontact])"
], */
/* uncomment above and comment below */
"data": [{"items": [93000, 58000, 102000, 66000, 43000, 24000], "hints": {"index": 0}}]
/* comment out the 'data' above and uncomment 'data' below */
/* "data": [
{
"items": [
131,
"3 – 6 months"
],
"hints": {
"index": 0
}
},
{
"items": [
78,
"6 months – 1 year"
],
"hints": {
"index": 1
}
},
{
"items": [
89,
"Can't remember"
],
"hints": {
"index": 2
}
},
{
"items": [
56,
"Over a year ago"
],
"hints": {
"index": 4
}
},
{
"items": [
442,
"Less than 3 months"
],
"hints": {
"index": 3
}
}
], */
}
renderCore ( sfdata );
display_data ( sfdata );
}
</script>
</body>
</html>
var dat4 = game.cache.getJSON('hint');
if (dat4.type == 'hint') {
var myText = dat4.data[0].message;
// alert(myText);
this.instructions = this.add.text(game.world.centerX, game.world.centerY,
myText, {
font: '50px lato',
fill: '#f5f5f5',
align: 'center'
}
);
this.instructions.stroke = "#7f34de";
this.instructions.strokeThickness = 16;
// Apply the shadow to the Stroke only
this.instructions.setShadow(1, 1, "#333333", 1, true, false);
this.instructions.anchor.setTo(0.5, 0.5);
this.time.events.add(3000, this.instructions.destroy, this.instructions);
alert(myText);
}
{
"type": "hint",
"data": [
{
"message": "xxxxxxxx"
}
]
}
I put this piece of code in my .js file. It performance well when I run on my computer, but it does not work when on the server. Could you please help me?
So, I am working on code that uses the DataTables API. It appears that it is using an older version of it though. So, my table updates every 5 seconds and all I need is for it to completely update when new new data comes in. However, while it input new update, data that is no longer referenced in that table stay there even though it should disappear, and my table just gets bigger and bigger over time. I've tried to use:
Table.fnClearTable(); // throws error below
TypeError: Cannot set property '_aData' of undefined
And this doesn't work. It removes everything, but won't let me rebuild a new table. I've also tried to use:
Table.fnDestroy(); // doesn't seem to work either
"bDestroy":true // didn't seem to work, but I couldn't tell
So, this is the particular function that I am working on. I'd like to to periodically either delete and recreate the table, or to do a better job at refreshing the data going into it.
my.updating.graph = function(obj, listAll) {
try {
if (obj == null || obj.updates == null || obj.updates.length == 0) {
$("#sectionUpdates").hide();
return;
}
$("#sectionUpdates").show();
var table = null;
if ($.fn.dataTable.isDataTable("updateTable")) { // may remove this statement...
table = $("#updateTable").dataTable();
} else {
table = $("#updateTable").dataTable({ // is there a reset option?
"paging": !listAll,
"pagingType": !listAll ? "X" : "Y",
"searching": true,
"order": [
[0, "desc"]
],
"ordering": true,
"oLanguage": {
"sEmptyTable": "No updates at this time"
},
"iDisplayLength": 15,
"info": false,
"formatNumber": function(format) {
return friendlyFormat(format, 1000, 0);
},
"aoColumns": [{
"bVisible": false
},
{
"className": "dt-center",
"width": "10%",
"iDataSort": 0,
"render": function(data, type, row) {
return extractData(data, type, row[0]);
}
}, {
"sType": "mixed-string",
"className": "dt-left",
"width": "30%",
"render": function(data, type, row) {
return getZData(data, type, row[1]);
}
}, {
"className": "dt-left",
"width": "30%",
"render": function(data, type, row) {
return getYData(data, type, row[2]);
}
}, {
"sType": "mixed-string",
"className": "dt-left",
"width": "30%",
"render": function(data, type, row) {
return getZData(data, type, row[3]);
}
}
]
});
$("#updateTable").resize(function() {});
}
var updates = obj.updates;
for (var i = 0; i < updates.length; i++) {
var update = updates[i];
var id = makeId(update.id);
var triggered = getCurrentUTC();
if (update) {
if (getID("updateTable", id) == null) {
var row = table.fnAddData([
update.field1,
update.field2,
update.field3,
update.field4
]);
var node = $("#updateTable").dataTable().fnSettings().aoData[row[0]].nTr;
node.setAttribute("id", "updateTable-item-" + id);
node.setAttribute("rowIdx", row[0]);
setID("updateTable", id, row[0]);
}
table.fnUpdate([
update.field1,
update.field2,
update.field3,
update.field4
], getID("updateTable", id),
null, false, false);
for (var q = 0; q < tblStatusClasses.length; q++) {
$("updateTable-item-" + id + " td:eq(0)").removeClass(tblStatusClasses[q]);
}
$("#updateTable-item-" + id + " td:eq(0)").addClass("table-state" + update.field1);
}
table.fnStandingRedraw();
}
} catch (e) {
console.log(e);
}
}
I am working with Dygraphs to chart Arduino sensor data.I need to get a subtract between two data so i am using php inside a script function but it doesn't work.It is possible to include
<script type="text/javascript">
var csv = [
'<?php
$row = 1;
if (($handle = fopen("https://api.thingspeak.com/channels/***/feed.csv?key=***&start=<?php echo $_POST['day_ini'];?>%20<?php echo $_POST['hour_ini'];?>&end=<?php echo $_POST['day_end'];?>%20<?php echo $_POST['hour_end'];?>", "r")) !== FALSE) {
...
?>','2015-11-02 20:54:50 UTC,1049703,5,5'
];
This is all my function code:
<script type="text/javascript">
var csv = [
'<?php
$row = 1;
if (($handle = fopen("https://api.thingspeak.com/channels/***/feed.csv?key=***&start=2015-11-02%2020:50:45&end=2015-11-02%2021:50:45", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 50, ",")) !== FALSE) {
if($row == 1){ $row++; continue; }
$num = count($data);
for ($c=0; $c < $num; $c++) {
if(strpos($data[$c], 'Finished') !== false) {
$c++;
echo $data[$c] . "," ; }
Else{
echo $data[$c] . "," ;
}
}
}
fclose($handle);
}
?>','2015-11-02 20:54:50 UTC,1049703,5,5'
//... etcetera
];
function getPairDifference(pair) {
//"pair" is a zero-based integer.
// "0" will return a difference between csv rows "0" & "1"
// "1" will return a difference between csv rows "1" & "2"
// etcetera...
var firstVal = parseInt(csv[pair].split(",")[3]);
var secondVal = parseInt(csv[pair + 1].split(",")[3]);
return firstVal - secondVal;
}
for (var i = 0; i < csv.length; i += 1) {
// Demo code to visualize numbers.
// Actual function call of interest is simply "getPairDifference( i )"
var plot = getPairDifference(i);
// $("<div></div>").text(plot).appendTo("body");
$(function() {
$("#chart3").chart({
template: "line_basic_6",
tooltips: {
serie1: [plot],
width:20,
height:15,
},
values: {
serie1: [plot]
},
labels: ["Period 1","Period 2"],
defaultSeries: {
type: "bar",
stacked: true
},
series: {
serie3: {
type: "line",
stacked: false,
axis: "r"
}
},
axis: {
r: {
max: 100,
suffix: "%"
}
}
});
});
$.elycharts.templates['line_basic_6'] = {
type: "line",
margins: [10, 40, 40, 30],
defaultSeries: {
highlight: {
newProps: {
r: 8,
opacity: 1
},
overlayProps: {
fill: "white",
opacity: 0.2
}
}
},
series: {
serie1: {
color: "90-#003000-#009000",
tooltip: {
frameProps: {
stroke: "green"
}
}
},
},
defaultAxis: {
labels: true
},
axis: {
x: {
labelsRotate: 0,
labelsProps: {
font: "11px Verdana"
}
}
},
features: {
grid: {
draw: true,
forceBorder: true,
ny: 5
}
},
barMargins: 180
};
}
</script>
Thanks in advance.
no need to echo like that and you are using <?php inside another <?php before closing that.
<script type="text/javascript">
var csv = [
'<?php
$row = 1;
if (($handle = fopen("https://api.thingspeak.com/channels/***/feed.csv?key=***&start={$_POST['day_ini']}%20{$_POST['hour_ini']}&end={$_POST['day_end']}%20{$_POST['hour_end']}", "r")) !== FALSE) {
}
?>', '2015-11-02 20:54:50 UTC,1049703,5,5'
];
</script>
And i am not sure of }, please check that once.
You have missunderstood something about PHP and Javascript.
Javascript gets sended to the Client, so it works in the Browser and also get's executed.
PHP altough gets executed on the Server first, there lies your problem, you can't execute on the Client something that needs to be done by a Server.
I am trying to use Fuelux repeater for one of my projects but I cant figure out how to populate data using javascript. The examples they have provided use couple of other plugins(Require.js and underscore.js) and I am not familiar with those. Can someone please help me to do this without any other plugins. I removed all require methods in the code but that didnt work either. Please look at this fiddle for what I have so far.
/*!
* JavaScript for Fuel UX's docs - Repeater Examples
* Copyright 2011-2014 ExactTarget, Inc.
* Licensed under the Creative Commons Attribution 3.0 Unported License. For
* details, see http://creativecommons.org/licenses/by/3.0/.
*/
define function(require){
// var $ = require('jquery');
// var _ = require('underscore');
var colors = {
bug: '#A8B820',
dark: '#705848',
dragon: '#7038F8',
electric: '#F8D030',
fairy: '#EE99AC',
fighting: '#C03028',
fire: '#F08030',
flying: '#A890F0',
ghost: '#705898',
grass: '#78C850',
ground: '#E0C068',
ice: '#98D8D8',
normal: '#A8A878',
poison: '#A040A0',
psychic: '#F85888',
rock: '#B8A038',
steel: '#B8B8D0',
water: '#6890F0'
};
var columns = [
{
label: 'Name',
property: 'name',
sortable: true
},
{
label: 'Id',
property: 'id',
sortable: true
},
{
label: 'Type',
property: 'type',
sortable: true
},
{
label: 'Height (in)',
property: 'height',
sortable: true
},
{
label: 'Weight (lbs)',
property: 'weight',
sortable: true
},
{
label: 'Abilities',
property: 'abilities',
sortable: true
},
{
label: 'Weakness',
property: 'weakness',
sortable: true
}
];
var delays = ['300', '600', '900', '1200'];
var pokemon = [{
"abilities": "Overgrow",
"weight": "15.2",
"weakness": "fire, flying, ice, psychic",
"height": "28.0",
"id": "001",
"name": "Bulbasaur",
"ThumbnailAltText": "Bulbasaur",
"ThumbnailImage": "http://assets2.pokemon.com/assets/cms2/img/pokedex/detail/001.png",
"type": "grass, poison"
},
{
"abilities": "Overgrow",
"weight": "28.7",
"weakness": "fire, flying, ice, psychic",
"height": "39.0",
"id": "002",
"name": "Ivysaur",
"ThumbnailAltText": "Ivysaur",
"ThumbnailImage": "http://assets3.pokemon.com/assets/cms2/img/pokedex/detail/002.png",
"type": "grass, poison"
},
{
"abilities": "Overgrow, Thick Fat",
"weight": "342.8",
"weakness": "fire, psychic, flying, ice",
"height": "94.0",
"id": "003",
"name": "Venusaur",
"ThumbnailAltText": "Venusaur",
"ThumbnailImage": "http://assets4.pokemon.com/assets/cms2/img/pokedex/detail/003.png",
"type": "grass, poison"
}];
var dataSource, filtering;
// require('bootstrap');
// require('fuelux');
dataSource = function(options, callback){
var items = filtering(options);
var resp = {
count: items.length,
items: [],
page: options.pageIndex,
pages: Math.ceil(items.length/(options.pageSize || 50))
};
var i, items, l;
i = options.pageIndex * (options.pageSize || 50);
l = i + (options.pageSize || 50);
l = (l <= resp.count) ? l : resp.count;
resp.start = i + 1;
resp.end = l;
if(options.view==='list' || options.view==='thumbnail'){
if(options.view==='list'){
resp.columns = columns;
for(i; i<l; i++){
resp.items.push(items[i]);
}
}else{
for(i; i<l; i++){
resp.items.push({
color: colors[items[i].type.split(', ')[0]],
name: items[i].name,
src: items[i].ThumbnailImage
});
}
}
setTimeout(function(){
callback(resp);
}, delays[Math.floor(Math.random() * 4)]);
}
};
filtering = function(options){
var items = $.extend([], pokemon);
var search;
if(options.filter.value!=='all'){
items = _.filter(items, function(item){
return (item.type.search(options.filter.value)>=0);
});
}
if(options.search){
search = options.search.toLowerCase();
items = _.filter(items, function(item){
return (
(item.name.toLowerCase().search(options.search)>=0) ||
(item.id.toLowerCase().search(options.search)>=0) ||
(item.type.toLowerCase().search(options.search)>=0) ||
(item.height.toLowerCase().search(options.search)>=0) ||
(item.weight.toLowerCase().search(options.search)>=0) ||
(item.abilities.toLowerCase().search(options.search)>=0) ||
(item.weakness.toLowerCase().search(options.search)>=0)
);
});
}
if(options.sortProperty){
items = _.sortBy(items, function(item){
if(options.sortProperty==='id' || options.sortProperty==='height' || options.sortProperty==='weight'){
return parseFloat(item[options.sortProperty]);
}else{
return item[options.sortProperty];
}
});
if(options.sortDirection==='desc'){
items.reverse();
}
}
return items;
};
// REPEATER
$('#repeaterIllustration').repeater({
dataSource: dataSource
});
$('#myRepeater').repeater({
dataSource: dataSource
});
$('#myRepeaterList').repeater({
dataSource: dataSource
});
$('#myRepeaterThumbnail').repeater({
dataSource: dataSource,
thumbnail_template: '<div class="thumbnail repeater-thumbnail" style="background: {{color}};"><img height="75" src="{{src}}" width="65"><span>{{name}}</span></div>'
});
}
You seem to be doing everything right.. Only thing you had to do was load jQuery on onLoad and comment out define function(require) statement..
JSFiddle