Attaching an Event Listener - titanium

I've just finished creating a meticulously generated grid of icons (imageViews) and now I need to be able to do something with them. What I'm finding, though, is that the event listener I'm trying to bind isn't getting bound. Window loads, my icons are displayed nicely, but they aren't clickable.
Can anyone see what I'm missing? The code below is a fully functional (except for the part that doesn't function) file. You should be able to copy it into a test app and load it right up (may be iPhone-only at the moment).
Any insight would be much appreciated.
// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Ti.UI.setBackgroundColor('#000');
//
// create base UI tab and root window
//
var win = Ti.UI.createWindow({
backgroundColor:'#fff',
layout: 'vertical',
navBarHidden: true,
});
// icon grid
var icons = [
{ image: '/images/ico_generic.png', label: 'Hospital Locations', url: 'http://google.com' },
{ image: '/images/ico_generic.png', label: 'Tobacco Free Campus', url: 'http:://robwilkerson.org' },
{ image: '/images/ico_generic.png', label: 'ER Wait Times', url: 'http://letmegooglethatforyou.com' },
{ image: '/images/ico_generic.png', label: 'Make a Donation', url: 'http://flickr.com/photos/robwilkerson' },
{ image: '/images/ico_generic.png', label: 'Condition Search', url: 'http://facebook.com' },
{ image: '/images/ico_generic.png', label: 'Video Library', url: 'http://google.com/reader' },
{ image: '/images/ico_generic.png', label: 'Financial Help', url: 'http://stackoverflow.com' },
{ image: '/images/ico_generic.png', label: 'Patient Forms', url: 'http://github.com' }
];
// put the grid in a scrollable view
var iconGrid = Ti.UI.createScrollView({
layout: 'vertical',
});
// incoming properties we want customizable
var cols = 3;
var icoW = 57;
var icoH = 57;
// Grid
var xSpacer = 10; // horizontal space b/t icons
var ySpacer = 10; // vertical space b/t icons
var rows = Math.ceil( icons.length / cols ); // how many rows?
// Container width = 1/3 of the viewport minus the icon widths and spacers
var containerW = Math.floor( ( Ti.Platform.displayCaps.platformWidth - ( xSpacer * ( cols + 1 ) ) ) / 3 );
// Container height = icon height + label spacer + label height
var containerH = icoH + ySpacer + 15;
// Row height = icon height + top spacer + bottom spacer + label spacer + 15 (label height)
var rowH = containerH + ( 2 * ySpacer );
// Incrementing values
var i = 0;
var viewHeight = 0;
for( var y = 0; y < rows; y++ ) {
var thisRow = Ti.UI.createView({
className: 'grid',
layout: 'horizontal',
height: rowH,
touchEnabled: false,
});
viewHeight += rowH;
for( var x = 0; x < cols && i < icons.length; x++ ) {
var container = Ti.UI.createView({
left: xSpacer,
height: containerH,
top: ySpacer,
width: containerW,
});
var icon = Ti.UI.createImageView({
left: ( containerW - icoW ) / 2,
height: icoH,
image: icons[i].image,
top: 0,
width: icoW,
});
var label = Ti.UI.createLabel({
// borderColor: '#00f',
font: { fontSize: 12 },
height: 15,
text: icons[i].label,
textAlign: 'center',
top: icoH + ySpacer,
width: containerW,
});
icon.addEventListener( 'click', function( e ) {
alert( 'Icon ' + i + ' was clicked' );d
});
container.add( icon );
container.add( label );
thisRow.add( container );
i++;
}
iconGrid.add( thisRow );
iconGrid.height = viewHeight;
}
win.add( iconGrid );
win.open();

You can also apply an event listener to the "view" itself. The reason being is, if you constantly add the same event listener to every single view, you'll cause the device's memory to become smaller and smaller, especially in cases where you'll have a larger data set.
My suggestion to you is this:
Add your own property to the imageView, like an "id" or something. So something like:
Ti.UI.createImageView({image: 'path/to/image.png', id: 'array_key'});
Once you've done that, you can add an event listener to the parent view, in this case your imageView.
view.addEventListener('click', function(e) {
alert(e.source.id + ' was clicked');
});
That way you have one event listener that can handle all the imageView events.

This one's on me. In my learning process, I went through a couple of different solutions to display a grid of icons. In one of the early iterations, I had to disable touch for the row (it was a tableView attempt). Several iterations later I got the display right, but disabling touch access on the row killed my ability to "click" the icons.
I was so far down the road that I didn't even realize that property was still in place until a new set of eyes pointed it out to me. Once I removed that property on thisRow, the event listeners got bound properly.

I am adding some line of code. What I have done is like created the grid of images and when you click, you will be able to that image.
{
"body": [
{
"type": "photo",
"order": 1,
"photos": [
{
"thumbnail": "http://www.flower.com/version_2.0/files/photos/thumbnails/745178756-_-1331130219.jpg",
"photo": "http://www.flower.com/version_2.0/files/photos/745178756-_-1331130219.jpg"
},
{
"thumbnail": "http://www.flower.com/version_2.0/files/photos/thumbnails/58062938-_-1337463040.jpg",
"photo": "http://www.flower.com/version_2.0/files/photos/58062938-_-1337463040.jpg"
},
{
"thumbnail": "http://www.flower.com/version_2.0/files/photos/thumbnails/1368715237-_-1337463149.jpg",
"photo": "http://www.flower.comversion_2.0/files/photos/1368715237-_-1337463149.jpg"
},
]
},
],
"status": true
}
It was response I was getting from the server.
Now for Making it is in grid and for clickable image, I am going to paste the code below. Note grid is done for 320 px width.
var xhr = Ti.Network.createHTTPClient({
onload : function(e) {
var response = JSON.parse(this.responseText);
var myObjectString = JSON.stringify(response);
Titanium.API.info('myObjectString--->: ' + myObjectString)
var myArray = response.body;
var objectArray = [];
var k = 5;
for (var i = 0; i < myArray[0].photos.length/5; i++) {
var l = 0+i*5; var m = 0 for (var j = l; j < k; j++) {
var thumb = Ti.UI.createImageView({
image:myArray[0].photos[j].thumbnail,
largeImage:myArray[0].photos[j].photo,
height:60,
tag:j,
width:60,
top:5*(i+1)+60*i,
left:3*(m+1)+60*m,
});
objectArray.push(thumb);
m++;
scroll.add(thumb);
thumb.addEventListener('click' ,function(e)
{
for(var i =0;i<objectArray.length;i++)
{
if(e.source.tag==objectArray[i].tag)
{
var LargeImageView = Ti.UI.createWindow({
backButtonTitle:'Image',
barColor:'#000',
backgroundColor: '#fff',
backgroundImage:'./Images/background.png',
url:'/More/DetailsImage.js',
image:objectArray[i].largeImage,
ImageArray:objectArray,
index:i,
});
Titanium.UI.currentTab.open(LargeImageView,{animated:true,modal:true});
break;
}
}
}); } l=k+5; k=k+5;
} } });

Related

jsPlumb + Panzoom infinite droppable canvas

I have created a codepen that uses jquery ui droppable(for drag/drop), jsPlumb (for flowcharting) and Panzoom (panning and zooming) to create a flowchart builder. You could drag the list items from the draggable container (1st column) to the flowchart (2nd column) and then connect the items using the dots to create a flowchart. The #flowchart is a Panzoom target with both pan and zoom enabled. This all works fine.
However, I would like to have the #flowchart div always span the whole area of the flowchart-wrapper i.e. the #flowchart should be an infinite canvas that supports panning, zooming and is a droppable container.
It should have the same effect as flowchart-builder-demo. The canvas there is infinite where you can drag and drop items (Questions, Actions, Outputs) from the right column.
Any pointers on how to achieve this (like the relevant events or multiple panzoom elements and/or css changes) would be greatly appreciated.
const BG_SRC_TGT = "#2C7BE5";
const HEX_SRC_ENDPOINT = BG_SRC_TGT;
const HEX_TGT_ENDPOINT = BG_SRC_TGT;
const HEX_ENDPOINT_HOVER = "#fd7e14";
const HEX_CONNECTOR = "#39afd1";
const HEX_CONNECTOR_HOVER = "#fd7e14";
const connectorPaintStyle = {
strokeWidth: 2,
stroke: HEX_CONNECTOR,
joinstyle: "round",
outlineStroke: "white",
outlineWidth: 1
},
connectorHoverStyle = {
strokeWidth: 3,
stroke: HEX_CONNECTOR_HOVER,
outlineWidth: 2,
outlineStroke: "white"
},
endpointHoverStyle = {
fill: HEX_ENDPOINT_HOVER,
stroke: HEX_ENDPOINT_HOVER
},
sourceEndpoint = {
endpoint: "Dot",
paintStyle: {
stroke: HEX_SRC_ENDPOINT,
fill: "transparent",
radius: 4,
strokeWidth: 3
},
isSource: true,
connector: ["Flowchart", { stub: [40, 60], gap: 8, cornerRadius: 5, alwaysRespectStubs: true }],
connectorStyle: connectorPaintStyle,
hoverPaintStyle: endpointHoverStyle,
connectorHoverStyle: connectorHoverStyle,
dragOptions: {},
overlays: [
["Label", {
location: [0.5, 1.5],
label: "Drag",
cssClass: "endpointSourceLabel",
visible: false
}]
]
},
targetEndpoint = {
endpoint: "Dot",
paintStyle: {
fill: HEX_TGT_ENDPOINT,
radius: 5
},
hoverPaintStyle: endpointHoverStyle,
maxConnections: -1,
dropOptions: { hoverClass: "hover", activeClass: "active" },
isTarget: true,
overlays: [
["Label", { location: [0.5, -0.5], label: "Drop", cssClass: "endpointTargetLabel", visible: false }]
]
};
const getUniqueId = () => Math.random().toString(36).substring(2, 8);
// Setup jquery ui draggable, droppable
$("li.list-group-item").draggable({
helper: "clone",
zIndex: 100,
scroll: false,
start: function (event, ui) {
var width = event.target.getBoundingClientRect().width;
$(ui.helper).css({
'width': Math.ceil(width)
});
}
});
$('#flowchart').droppable({
hoverClass: "drop-hover",
tolerance: "pointer",
drop: function (event, ui) {
var helper = $(ui.helper);
var fieldId = getUniqueId();
var offset = $(this).offset(),
x = event.pageX - offset.left,
y = event.pageY - offset.top;
helper.find('div.field').clone(false)
.animate({ 'min-height': '40px', width: '180px' })
.css({ position: 'absolute', left: x, top: y })
.attr('id', fieldId)
.appendTo($(this)).fadeIn('fast', function () {
var field = $("#" + fieldId);
jsPlumbInstance.draggable(field, {
containment: "parent",
scroll: true,
grid: [5, 5],
stop: function (event, ui) {
}
});
field.addClass('panzoom-exclude');
var bottomEndpoints = ["BottomCenter"];
var topEndPoints = ["TopCenter"];
addEndpoints(fieldId, bottomEndpoints, topEndPoints);
jsPlumbInstance.revalidate(fieldId);
});
}
});
const addEndpoints = (toId, sourceAnchors, targetAnchors) => {
for (var i = 0; i < sourceAnchors.length; i++) {
var sourceUUID = toId + sourceAnchors[i];
jsPlumbInstance.addEndpoint(toId, sourceEndpoint, { anchor: sourceAnchors[i], uuid: sourceUUID });
}
for (var j = 0; j < targetAnchors.length; j++) {
var targetUUID = toId + targetAnchors[j];
jsPlumbInstance.addEndpoint(toId, targetEndpoint, { anchor: targetAnchors[j], uuid: targetUUID });
}
$('.jtk-endpoint').addClass('panzoom-exclude');
}
// Setup jsPlumbInstance
var jsPlumbInstance = jsPlumb.getInstance({
DragOptions: { cursor: 'pointer', zIndex: 12000 },
ConnectionOverlays: [
["Arrow", { location: 1 }],
["Label", {
location: 0.1,
id: "label",
cssClass: "aLabel"
}]
],
Container: 'flowchart'
});
// Setup Panzoom
const elem = document.getElementById('flowchart');
const panzoom = Panzoom(elem, {
excludeClass: 'panzoom-exclude',
canvas: true
});
const parent = elem.parentElement;
parent.addEventListener('wheel', panzoom.zoomWithWheel);
I've just been working on the exact same issue and came across this as the only answer
Implementing pan and zoom in jsPlumb
The PanZoom used looks to be quite old - but the idea was the same, use the JQuery Draggable plugin for the movable elements, instead of the in-built JsPlumb one. This allows the elements to move out of bounds.
The below draggable function fixed it for me using the PanZoom library.
var that = this;
var currentScale = 1;
var element = $('.element');
element.draggable({
start: function (e) {
//we need current scale factor to adjust coordinates of dragging element
currentScale = that.panzoom.getScale();
$(this).css("cursor", "move");
that.panzoom.setOptions({ disablePan: true });
},
drag: function (e, ui) {
ui.position.left = ui.position.left / currentScale;
ui.position.top = ui.position.top / currentScale;
if ($(this).hasClass("jtk-connected")) {
that.jsPlumbInstance.repaintEverything();
}
},
stop: function (e, ui) {
var nodeId = $(this).attr('id');
that.jsPlumbInstance.repaintEverything();
$(this).css("cursor", "");
that.panzoom.setOptions({ disablePan: false });
}
});
I'm not sure if redrawing everything on drag is that efficient - so maybe just redraw both the connecting elements.

JqPlot EnhancedLegendRenderer with Mouse events

I am using JqPlot to display some graph legends on the jqplotMouseEnter, and jqplotMouseLeave events.
Here is my code:
$('#FinancialsLineGraph').bind('jqplotMouseEnter', function(ev, seriesIndex, pointIndex, data) {
$('#FinancialsLineGraph .jqplot-table-legend').show();
});
$('#FinancialsLineGraph').bind('jqplotMouseLeave', function(ev, seriesIndex, pointIndex, data) {
$('#FinancialsLineGraph .jqplot-table-legend').hide();
});
With this above code, when the cursor is moved over the actual legend inside the graph, the legend 'flickers' and the user cannot use the EnhancedLegendRenderer to shown/hide the corresponding series in the plot.
How can I get this above feature working?
Thanks in advance.
EDIT
Here is my JS plot code.
var plotCogsLineGraph = $.jqplot('FinancialsLineGraph', [[30,31,34,40,45], [34,38,31,42,38]],
{
axes:
{
xaxis:
{
ticks: ['5','4','3','2','1']
},
yaxis:
{
label:'%',
pad: 1.05,
ticks: ['0','15','30','45','60']
}
},
width: 480, height: 270,
legend:{show:true, location: 's', placement: 'insideGrid', renderer: $.jqplot.EnhancedLegendRenderer},
seriesDefaults:
{
rendererOptions: {smooth: true}
},
series:[
{
lineWidth:1,
label:'COGS',
markerOptions: { size:1, style:'dimaond' }
},
{
lineWidth:1,
label:'Wages',
markerOptions: { size: 1, style:"dimaond" }
}
]
}
);
What's actually happening here is that the jqplotMouseLeave event is being raised when you enter the legend, causing it to not be displayed, which then raises the jqplotMouseEnter (when the legend is hidden, you all of a sudden enter the plot), causing it to be shown. Because of this cycle, you get the flickering.
Try changing your 'jqplotMouseLeave handler to this:
$('#FinancialsLineGraph).bind('jqplotMouseLeave', function(ev, seriesIndex, pointIndex, data) {
var top, right, bottom, left;
var legend = $('#FinancialsLineGraph .jqplot-table-legend');
top = legend.offset().top;
left = legend.offset().left;
bottom = top + legend.height();
right = left + legend.width();
if (!(ev.pageX >= left && ev.pageX <= right && ev.pageY >= top && ev.pageY <= bottom)) {
$('#chart1 .jqplot-table-legend').hide();
}
});
What this does is hide the legend only if the mouse cursor location is not contained within the legend's bounding box.

how to listen to click events on group of imageViews in appcelerator

I'm creating some imageViews as below.
// Time buttons
var timeButtons =[
{ title: 'Afternoon', path: 'images/others/time/afternoon.png'},
{ title: 'CurrentTime', path: 'images/others/time/currenttime.png'},
{ title: 'Evening', path: 'images/others/time/evening.png'}
]
createButtons(timeButtons);
/* Button creation function */
function createButtons(data){
for (var i = 0; i < data.length; i++){
//Creating each button
var button = Titanium.UI.createImageView({
image: data[i].path,
height: 90,
width: 90,
top: 20+90*i+20*i,
value: 1
});
//Adding the buttons to the center view
centerButtons.add(button);
}
}
Now when a user clicks on any of the imageView, I want to identify which imageView it clicked and do something accordingly.
you can additional add parameters to you imageView. Like id or so.
Here your example with an additional parameter:
for (var i = 0; i < data.length; i++){
//Creating each button
var button = Titanium.UI.createImageView({
_id: i, // Your custom parameter
image: data[i].path,
height: 90,
width: 90,
top: 20+90*i+20*i,
value: 1
});
//Adding the buttons to the center view
centerButtons.add(button);
}
Than you can use the new parameter to identify your imageView:
centerButtons.addEventListener('click', function(event)
{
// Perhaps you should check here if the custom parameter ( _id ) exist.
switch(event.source._id){
case 0:
// Your stuff with you first image
break;
// etc.
}
});
centerButtons.addEventListener('click', function(evt) {
alert(evt.source.image);
});

FullCalendar and Flot Resize Conflict

I've successfully integrated both a Flot line graph and an instance of FullCalendar into my site. They are both on separate pages (although the pages are loaded into a div via AJAX).
I've added the Flot Resize plugin and that works perfectly, re-sizing the line graph as expected. However, it seems to cause an error when resizing the calendar.
Even if I load the calendar page first, when I resize the window I get this error in the console (also, the calendar does not resize correctly):
TypeError: 'undefined' is not an object (evaluating 'r.w=o!==c?o:q.width()')
I was struggling to work out where the error was coming from, so I removed the link to the Flot Resize JS and tried again. Of course the line graph does not resize, but when resizing the calendar, it works correctly.
The div containers for the two elements have different names and the resize function is called from within the function to draw the line graph (as required).
I have tried moving the link to the Flot Resize plugin into different places (i.e. above/below the fullCalendar JS, into the template which holds the graph), but all to no avail.
Does anyone have any idea where the conflict might be and how I might solve it??
Thanks very much!
EDIT: It seems that the error is also triggered when loading the line graph (flot) page AFTER the fullcalendar page even without resizing the window.... Now I am very confused!
EDIT 2: The code which draws the line graph. The function is called on pageload and recieves the data from JSON pulled off the server. When the graph is loaded, I still get the error about shutdown() being undefined.
function plotLineGraph(theData){
var myData = theData['data'];
var myEvents = theData['events'];
var myDates = theData['dates'];
var events = new Array();
for (var i=0; i<myEvents.length; i++) {
events.push(
{
min: myEvents[i][0],
max: myEvents[i][1],
eventType: "Calendar Entry",
title: myEvents[i][2],
description: myEvents[i][3]
}
);
}
function showTooltip(x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css( {
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 5,
border: '1px solid #fdd',
padding: '2px',
'background-color': 'black',
opacity: 0.80
}).appendTo("body").fadeIn(200);
}
var previousPoint = null;
$("#placeholder").bind("plothover", function (event, pos, item) {
$("#x").text(pos.x.toFixed(2));
$("#y").text(pos.y.toFixed(2));
if ($("#enableTooltip:checked").length == 0) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
if(item.series.label != null){
showTooltip(item.pageX, item.pageY,
item.series.label + " of " + y);
}
}
}
else {
$("#tooltip").remove();
previousPoint = null;
}
}
});
var d1 = [
myData[0], myData[1], myData[2], myData[3], myData[4],
myData[5], myData[6], myData[7], myData[8], myData[9],
myData[10], myData[11], myData[12], myData[13], myData[14],
myData[15], myData[16], myData[17], myData[18], myData[19],
myData[20], myData[21], myData[22], myData[23], myData[24],
myData[25], myData[26], myData[27], myData[28], myData[29]
];
var markings = [
{ color: '#FFBDC1', yaxis: { from: 0, to: 2 } },
{ color: '#F2E2C7', yaxis: { from: 2, to: 3.5 } },
{ color: '#B6F2B7', yaxis: { from: 3.5, to: 5 } }
];
$.plot($("#placeholder"), [
{label: "Average Daily Rating", data: d1, color: "black"}
], {
events: {
data: events,
},
series: {
lines: { show: true },
points: { show: true }
},
legend: { show: true, container: '#legend-holder' },
xaxis: {
ticks:[
myDates[0], myDates[1], myDates[2], myDates[3], myDates[4],
myDates[5], myDates[6], myDates[7], myDates[8], myDates[9],
myDates[10], myDates[11], myDates[12], myDates[13], myDates[14],
myDates[15], myDates[16], myDates[17], myDates[18], myDates[19],
myDates[20], myDates[21], myDates[22], myDates[23], myDates[24],
myDates[25], myDates[26], myDates[27], myDates[28], myDates[29]
],
},
yaxis: {
ticks: 5,
min: 0,
max: 5
},
grid: {
backgroundColor: { colors: ["#fff", "#eee"] },
hoverable: true,
clickable: true,
markings: markings
},
selection: {
color: 'white',
mode: 'x'
},
});
$('#placeholder').resize();
$('#placeholder').shutdown();
}
EDIT 3:
The calendar is called like this:
function showCalendar() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$('#fullcalendar').fullCalendar({
header: {
left: 'prev',
center: 'title',
right: 'next'
},
clickable: true,
firstDay: 1,
eventSources: [
{
url: '/populate-calendar/{{theProductUuid}}/',
color: 'black',
data: {
text: 'text'
}
}
],
eventClick: function(calEvent, jsEvent, view) {
var startDate = $.fullCalendar.formatDate(calEvent.start, 'yyyy-MM-dd');
var endDate = $.fullCalendar.formatDate(calEvent.end, 'yyyy-MM-dd');
var eventId = calEvent.uuid;
$('#modal-event-title').text(calEvent.title);
$('#edit-event-name').val(calEvent.title);
$('#edit-start-date').val(startDate);
$('#edit-end-date').val(endDate);
$('#edit-event-text').val(calEvent.text);
$('#edit-event-btn').attr('data-uuid', eventId);
$('#modal-edit-event').on('click', '#delete-btn', function(){
deleteCalendarEvent(eventId);
});
$('#modal-edit-event').modal();
},
});
}
The AJAX to load the page containing the flot chart:
function loadDetailedReports(uuid){
$('#product-content').fadeOut('slow', function(){
$('#product-content').empty();
$('#whole-product-sub-nav .active').removeClass('active');
$('#detailed-reports-content').load('/detailed-reports/' + uuid + '/', function(){
$('#detailed-reports-btn').addClass('active');
$('#detailed-reports-content').fadeIn('slow', function(){
if (authorized){
setLocationHash('loadDetailedReports&' + uuid);
getChartData(uuid);
} else {
setLocationHash('');
}
});
});
});
}
And the AJAX to load the page containing the calendar:
function loadCalendar(uuid){
$('#detailed-reports-content').empty().hide();
$('#product-content').fadeOut('slow', function(){
$('#whole-product-sub-nav .active').removeClass('active');
$('#product-content').load('/calendar/' + uuid + '/', function(){
$('#calendar-btn').addClass('active');
$('#product-content').fadeIn('slow', function(){
if (authorized){
setLocationHash('loadCalendar&' + uuid);
} else {
setLocationHash('');
}
showCalendar();
});
});
});
}
The calls to .resize and .shutdown are there because I was under the impression that they are necessary to achieve the resizing function and in response to your earlier comment regarding shutdown...... They're quite possibly n00b errors........?!?!
It looks like this is triggering on line 198 of jquery-resize:
data.w = w !== undefined ? w : elem.width();
This sounds like a race-condition stemming from the way you load different content into the same div. Flot binds the resize event to the chart div, and only un-binds it if the plot is destroyed cleanly.
EDIT: Looking at your code, my first suggestion would be to get rid of the resize and shutdown calls at the end of plotLineGraph. The resize plugin doesn't require any setup; it hooks into Flot to attach automatically to any new plot. So your call to resize is actually to jQuery's resize event trigger, which may be what's causing the error.
EDIT #2: I'm still not clear on your structure, but to generalize: anywhere that you might be getting rid of #placeholder (via emptying its parent or anything like that) you should first call shutdown on the plot object. If you aren't keeping a reference to it, you can do it like this: $("#placeholder").data("plot").shutdown(); but then have to account for the fact that it's undefined prior to the creation of your first plot.
If that still doesn't work, I'd need to see a live (simplified) example to make any further suggestions.

Dojo slider problem - how to add numbers with slider

I have Dojo slider and I need to put from 0 to 24 h (0,1,2, ... 24).How to achive this ?
I have this:
<div id="vertical_monday" style="float: left;"></div>
and create like this :
var vertical_monday = dojo.byId("vertical_monday");
var rulesNodeMonday = document.createElement('div');
vertical_monday.appendChild(rulesNodeMonday);
var sliderRulesMonday = new dijit.form.VerticalRule({
count: 24,
style: "width:5px;"
},
rulesNodeMonday);
var slider = new dijit.form.VerticalSlider({
name: "vertical_monday",
value: 0,
minimum: 1440,
maximum: 0,
pageIncrement:100,
showButtons:true,
slideDuration:289,
discreteValues: 289,
intermediateChanges:true,
style: "height:500px;",
onChange: function(value) {
//dojo.byId("sliderValueMonday").value = value;
set_time_labels('mon',used_length['mon'],value);
val['mon']=value;
var a=(500*(value-used_length['mon']))/1440;
var temp_id='mon_'+temp_daily_plan['mon'];
$('#'+temp_id).css('height',a);
}
},
vertical_monday);
but it doesn't have numbers . How to add numbers ?
Here's a quick and dirty way to do it, not sure if it's the recommended one.
Add a container for the labels, just like you did with the ruler.
var labelsNodeMonday = document.createElement("div");
vertical_monday.appendChild(labelsNodeMonday);
Then create a dijit.form.VerticalRuleLabels instance and place it in that node, explicitly providing the labels as an array:
var labelsMonday = new dijit.form.VerticalRuleLabels({
labels: ["1h", "2h", "3h", "4h"] //.. and so on
}, labelsNodeMonday);
Or alternatively, if you don't like to repeat yourself.
var labelsMonday = new dijit.form.VerticalRuleLabels({
getLabels: function() {
for(var labels = [], i = 1; i <=24; i++) labels.push(i+"h");
return labels;
},
}, labelsNodeMonday);
Again, I don't know if this is the kosher way. Ideally, there should be something along the lines of:
var labelsMonday = new dijit.form.VerticalRuleLabels({
minimum: 1, maximum: 24, step: 1,
formatLabel: function(value) { return value + "h"; }
}, labelsNodeMonday);
.. but afaik there isn't at the moment.