How to dynamically remove imageViews stacked up on one another - uiimageview

I have tried the following code, the task I am trying to do is to first populate the window with an image stack and then every time you click on one, it removes it one by one.
var colors = ['red', 'blue', 'yellow', 'green', 'gray', 'black'];
for (var i in colors) {
var image = Titanium.UI.createImageView({
backgroundColor : colors[i],
top : 50,
left : 30,
width : 200,
height : 200
});
$.win.add(image);
}
image.addEventListener('click', function(e) {
alert(e);
alert(JSON.stringify(e.source));
$.win.remove(image);
});
and then when they click on each image, it gets removed from the window - the next one is then shown.
The event listener works fine for the first image view, but then stops working with the underlying ones.
I know that this can easily be done with a scrollableView, but I would like to try and do this using an image View stack.
Cheers.

You have to put the event listener inside the loop !
var colors = ['red', 'blue', 'yellow', 'green', 'gray', 'black'];
for (var i in colors) {
var image = Titanium.UI.createImageView({
backgroundColor : colors[i],
top : 50,
left : 30,
width : 200,
height : 200
});
//this is what you should do
image.addEventListener('click', function(e) {
alert(e); alert(JSON.stringify(e.source)); $.win.remove(image);
});
$.win.add(image);
}

Try this:
var colors = ['red', 'blue', 'yellow', 'green', 'gray', 'black'];
function imageHandler(_imgObj,_win)
{
_imgObj.addEventListener('click', function(e) {
alert(e);
alert(JSON.stringify(e.source));
_win.remove(image);
});
}
for (var i in colors) {
var image = Titanium.UI.createImageView({
backgroundColor : colors[i],
top : 50,
left : 30,
width : 200,
height : 200
});
imageHandler(image,$.win);
$.win.add(image);
}
What this does is remove the handler separates the handler and gives you more control. Through each iteration in the for-loop, each image has it's own handler defined and this should work.

Related

Drawing a spreadsheet like grid in canvas with konva

I am working on a Gantt-like task display using HTML5 canvas, and the Konvajs canvas library.
Deconstructing a Gantt chart into its components leads me currently to a view as below. Here 1 is the list of tasks, 2 is the task bar area, 3 is a task bar, and 4 is a text cell.
For this question I am seeking code to construct 1 & 4. The data to be displayed will be delivered in plain JS objects with a nested list of tasks where each task has a number, name, assigned-to person name, start date, end date, days duration, and % complete.
So the requirement is to be able to construct a spreadsheet-like panel such as is seen on the left hand side of a Gantt chart.
I have something part developed which I shall post as an answer. However this seems like such as common need that I am hoping there is someone out there with code they can cut & paste into SO to lead the way.
Note: Gantt in sample image is from Vertex42.
So here is my own fumbling attempt at an approach. Can anyone improve upon it or am I going down the wrong road.
EDIT: I now have a fledgling component for drawing text into the spreadsheet-like cells, including the percent complete shading. To keep this answer uncluttered, this additional component is in this codepen.
// this is the object that defines our grid
//
var gridData = { name: 'grid1', width: 350, height: 400, rowHeight: 24, padding: 4, fill: 'azure', gridLineColor: '#ccc', header: {size: 16, fill: 'black', color: 'white' }, data: {size: 16, fill: 'azure', color: 'black' },
row: [
{ cells: // row 1
[
{ width: 50, text: 'Item', style: 'header'},
{ width: 240, text: 'Name', style: 'header'},
{ width: 60, text: 'Status', style: 'header'},
]
},
{ cells: // row 2
[
{ text: '1'},
{ text: 'Find tea pot'},
{ text: '100%'},
]
},
{ cells: // row 3
[
{ text: '2'},
{ text: 'Boil water'},
{ text: '60%'},
]
}
]
}
// From here on could be wrapped into a component that churns out grids. Maybe you pass in the id of the stage container
// and the data model you want to produce, etc.
// Set up the canvas / stage
var stage = new Konva.Stage({container: 'container1', width: 600, height: 300});
// Add a layer
var layer = new Konva.Layer({draggable: false});
stage.add(layer);
// make a main group for the grid, call it a panel. Assigning a name may be handy later
var panel = new Konva.Group({name: gridData.name});
layer.add(panel); // Add the panel to the layer
// a group has no visual properties. Add a background rect to hold the colour fill
var panelRect = new Konva.Rect({width: gridData.width, height: gridData.height, fill: gridData.fill})
panel.add(panelRect);
var topLeft = {x: 0, y: 0}; // Since we are drawing a grid, we need to compute the position of each cell
for (var i = 0; i < gridData.row.length; i = i + 1){
topLeft.x = 0; // reset x at start of each row
// iterate for each cell on the row
for (var j = 0; j < gridData.row[i].cells.length; j = j + 1){
var cell = new Konva.Rect({name: 'cellBg', // assign a name for later searching
x: topLeft.x, y: topLeft.y, // position as computed
width: gridData.row[0].cells[j].width, // use the first row from celldate to get the cell width
height: gridData.rowHeight, // grid has a uniform row height
stroke: gridData.gridLineColor, // and line colour
strokeWidth: 1, // use a set line width but you can add to the gridData object as needed.
fill: (i === 0 ? gridData.header.fill : gridData.data.fill), // use the given header text color
});
panel.add(cell);
// Add text to the cell. Note that if you wanted to be using alignments you would need to draw the text off-screen and
// get width/height of that text then use those values for positioning calculations. Once you have the rect size of the
// text, all the alignments are simple math.
var text = new Konva.Text({ x: topLeft.x + gridData.padding, // add padding to locate the text nicely into the cell
y: topLeft.y + gridData.padding,
// use the given text size
fontSize: (i === 0 ? gridData.header.size : gridData.data.size),
// use the given header text color
fill: (i === 0 ? gridData.header.color : gridData.data.color),
text: gridData.row[i].cells[j].text, // set the text value.
listening: false // stop text interfering with mouse events
});
panel.add(text);
cell.on('mouseover', function(evt){
var shape = evt.target;
$(shape).data('bgColor', shape.fill());
shape.fill('lime');
layer.draw();
})
cell.on('mouseout', function(evt){
var shape = evt.target;
shape.fill($(shape).data('bgColor'));
layer.draw();
})
topLeft.x = topLeft.x + gridData.row[0].cells[j].width; // offset the computed next cell x value by the width of the cell
}
topLeft.y = topLeft.y + gridData.rowHeight; // offset the computed next cell y value by the height of the row
}
layer.draw();
stage.draw();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.5.1/konva.min.js"></script>
<div id='container1' style="width: 300px, height: 200px; background-color: silver;"></div>

jqplot help for barclustered type chart

hFollowing is the code for barclustered jqplot. can anyone please guide me gow to create a highlighted array in following code dynamically
$(document).ready(function(){
// For horizontal bar charts, x an y values must will be "flipped"
// from their vertical bar counterpart.
var plot2 = $.jqplot('chart2', [
[[2,1], [4,2], [6,3], [3,4]],
[[5,1], [1,2], [3,3], [4,4]],
[[4,1], [7,2], [1,3], [2,4]]], {
seriesDefaults: {
renderer:$.jqplot.BarRenderer,
// Show point labels to the right ('e'ast) of each bar.
// edgeTolerance of -15 allows labels flow outside the grid
// up to 15 pixels. If they flow out more than that, they
// will be hidden.
pointLabels: { show: true, location: 'e', edgeTolerance: -15 },
// Rotate the bar shadow as if bar is lit from top right.
shadowAngle: 135,
// Here's where we tell the chart it is oriented horizontally.
rendererOptions: {
barDirection: 'horizontal'
}
},
axes: {
yaxis: {
renderer: $.jqplot.CategoryAxisRenderer
}
}
});
});
You have a problem with your Javascript syntax and algorithm. The loop should looks like :
VData="9,453,470,232|488,378,375,142|365,275,255,434|217,317,479,89";
var a = new Array();
var split_fst = VData.split("|")
for(m=0;m<split_fst.length;m++) {
var split_snd = split_fst[m].split(",");
a[m] = new Array();
for(j=0;j<split_snd.length;j++){
a[m][j]=split_snd[j];
}
}
Your a variable now looks like : `[["9","453","470","232"],["488","378","375","142"],["365","275","255","434"],["217","317","479","89"]]

Titanium - Crop portion of image

How would you crop a small portion of a big image (e.g area of an imageview visible in a transparent frame) in appcelerator titanium for both iOS and android? imageAs** functions won't work as they aren't supported below android 3.0 . Here is my code:
var win=Ti.UI.createWindow({backgroundColor: 'white'})
var ImageView = Titanium.UI.createImageView({
width:200, height:200,
});
var cropView = Titanium.UI.createView({
width: 150,
height: 150,
borderColor: 'red',
borderWidth: 1,
zIndex: 1,
});
var button= Ti.UI.createButton({
bottom: 30,
width: 60,
title: 'OK',
zIndex: 1,
})
win.add(cropView)
Ti.Media.openPhotoGallery({
PhotoGalleryOptionsType : Ti.Media.MEDIA_TYPE_PHOTO,
success: function(e){
ImageView.image=e.media;
win.add(ImageView)
}, });
button.addEventListener('click',function(e)
{
// crop the visible area
})
I am using iOS 5 and android 2.2. Thanks for your help.
Add ImageView to cropView (rather than to win), position and size imageView so that the portion you want displayed is displayed (using negative values for left and top), and then call cropView.toImage(). You can use the resulting blob in a new image view, save it to a file, email it as an attachment, whatever you want.
Any portion of the image outside of its parents bounds will be cropped, leaving only the portion you specify.
I have done some small changes and now its all functional. Cheers!! :)
var win = Ti.UI.createWindow({
backgroundColor : 'white'
})
var orignal = Titanium.UI.createImageView({
width : Ti.UI.SIZE,
height : Ti.UI.SIZE,
left:5
});
var ImageView = Titanium.UI.createImageView({
width : 200,
height : 200
});
var cropView = Titanium.UI.createView({
top : 10,
width : 150,
height : 150,
borderColor : 'lime',
borderWidth : 1,
zIndex : 1,
left:150
});
var button = Ti.UI.createButton({
bottom : 30,
width : 60,
title : 'CROP',
zIndex : 1,
});
win.add(button);
Ti.Media.openPhotoGallery({
PhotoGalleryOptionsType : Ti.Media.MEDIA_TYPE_PHOTO,
success : function(e) {
ImageView.image = e.media;
orignal.image=e.media;
cropView.add(ImageView);
win.add(cropView);
win.add(orignal);
},
});
var CropedImageView = Titanium.UI.createImageView({
top : 200,
width : cropView.width,
height : cropView.height,
left:150
});
button.addEventListener('click', function(e) {
cropView.borderColor='transparent';
CropedImageView.image = cropView.toImage();
win.add(CropedImageView);
});
win.open();
I learnt some of this while my stay at Oodles Technologies.
Here's my contribution :
In this example you will see how to crop image in iOS Titanium.
To crop a image first create scroll view, define its maxZoomScale, minZoomScale.
maxZoomScale:-
Maximum Scaling factor of the scrollable region and its content.
minZoomScale:-
Minimum Scaling factor of the scrollable region and its content
maxZoomSale and minZoomScale we can adjust according to required.
then we have to add image view inside scrollview, then we can zoom in and zoom out image, to crop a image just need to click on crop button.
var window = Ti.UI.createWindow({
backgroundColor : 'white'
});
var scrollView = Ti.UI.createScrollView({
height : 260,
width : Ti.UI.FILL,
maxZoomScale : 4.0,
minZoomScale : 1.0,
zoomScale : 1.0,
});
window.add(scrollView);
var imageView = Ti.UI.createImageView({
height : scrollView.height,
width : scrollView.width,
backgroundColor : "transparent",
anchorPoint : {
x : 0.5,
y : 0.5
},
image : 'Default-568h#2x.png',
});
scrollView.add(imageView);
var button = Ti.UI.createButton({
top : 20,
title : 'Crop Button'
});
window.add(button);
button.addEventListener('click', function(e) {
button.hide();
var cropimage = scrollView.toImage();
var cropImageView = Ti.UI.createImageView({
top : 20,
height : 120,
width : 120,
image : cropimage
});
window.add(cropImageView);
});
window.open();

Weird and unpredictable behavior by Views and Images from remote URL?

Here is my
APP.js
var win = Ti.UI.createWindow({
navBarHidden : true,
className : 'window',
backgroundColor : "#efefef"
});
var header = Ti.UI.createView({
height : 20,
width : 303,
top : 0,
backgroundColor : "#abc"
});
win.add(header);
var scroll = Ti.UI.createScrollView({
top : 44,
bottom : 44,
layout : 'vertical'
});
win.add(scroll);
header.addEventListener('click', function(evt) {
fetch_images();
});
win.open();
function fetch_images() {
var xhr = Ti.Network.createHTTPClient({
onload : function() {
myjson = JSON.parse(this.responseText);
for ( i = 0; i < myjson.length; i++) {
Ti.API.debug(i);
var look = new looks(myjson[i])
scroll.add(look);
}
},
onerror : function(e) {
Ti.API.debug("STATUS: " + this.status);
Ti.API.debug("TEXT: " + this.responseText);
Ti.API.debug("ERROR: " + e.error);
if (Titanium.Network.online) {
alert('No reponse from server.');
} else {
alert('Please Check your Internet connectivity.');
}
},
timeout : 5000
});
xhr.open('GET', 'http://xxxxxxx.com/xxxxxxx.json?api_token=xxxxxxxx');
xhr.send();
}
function looks(image_details) {
var look_container = Ti.UI.createView({
height : 325,
width : 303,
top : 10,
layout : 'horizontal',
backgroundColor : "#cac"
});
var look_image = i.UI.createImageView({
width : 303,
top : 0,
left : 0,
right : 0,
image : image_details.image_medium
});
look_container.add(look_image);
return look_container;
}
I am about to pull my hairs from my head.
Working with this for around last 4-5 hours.
Acc. to the code Image should be something like this
But it appears like this.
Any guess whats wrong !! Any help would be grateful ??
As per the code Image should be aligned to top (0px from top). But Image is always down the line in the view and dont stick to the top... ??
-------------------------EDIT---------------------------
I editted my code to check for static JPG images
and its same even for the Images in the resources directory
check this question developer.appcelerator.com/question
code
var win = Ti.UI.createWindow({
navBarHidden : true,
className : 'window',
backgroundColor : "#efefef"
});
var my_container = Ti.UI.createView({
height : 325,
width : 303,
top : 30,
backgroundColor : "#cac",
layout : "horizontal"
});
var my_image = Ti.UI.createImageView({
width : '100%',
top : 0,
left : 0,
right : 0,
image : 'hello.jpg'
});
my_container.add(my_image);
win.add(my_container);
my_container.addEventListener('click', function() {
my_image.top = my_image.top - 25;
})
win.addEventListener('click', function() {
my_image.top = my_image.top + 5;
})
win.open();
and image url for the image to be used.
The problem is not the layout properties, it is image scaling! Note first that you are passing a larger image than the view, so Titanium does some scaling under the sheets.
So when you define the width of that ImageView, if the image you pass is bigger than the view, Titanium scales it using its own mechanism, which obviously, is not what you want, since it has been causing you to tear your hair out the past few days. I believe they scale images from the bottom up, causing your weird problem.
To fix this, you need to take control of the image scaling from Titanium, and pass a new, resized image
To do this, we need to get the original height and width of the image, to preserve the aspect ratio, then figure out a new size, resize the image, and pass it to the imageView.
To get the height and width of the image you kind of have to hack around a bit, here is how I did it with SDK 2.1.1.GA:
Get Height and Width of a Blob / Image
// Load the image as a blob to get height information
var imageFile = Ti.Filesystem.getFile('hello.png');
var blobOfImage = imageFile.read();
// Put it in a imageView, since It wont let me get height from a blob for some reason
var imageView1 = Titanium.UI.createImageView({
image: blobOfImage,
width: 'auto',
height: 'auto',
});
// This is the important part, toImage this view and you get the height and width of this image
// For some reason we cant get this from a Blob in SDK 2.1.1.GA
var heightOfImage = imageView1.toImage().height;
var widthOfImage = imageView1.toImage().width;
Now we calculate the aspect ratio for the width (screen size for iPhone of 320).
Aspect Ratio
var aspectRatio = heightOfImage / widthOfImage;
And now we can create the new resized image in the imageview.
New Image!
var my_container = Ti.UI.createView({
height : 325,
width : 303,
top : 30,
backgroundColor : "#cac",
layout : "horizontal"
});
var my_image = Ti.UI.createImageView({
top : 0,
left : 0,
right : 0,
image : blobOfImage.imageAsResized(320, 320*aspectRatio) // Note the resize call to the image blob
});
Here is the final output :
So I guess the lesson is dont trust Titanium to scale your images for you.

Titanium mobile - addEventListener on a view

i'm making a scrollable menu using common JS.
An item of the menu is a view that contains 2 others components :
a imageView for the icon, and a label for the text of this menu.
The comportement is strange and not the same on the android and ios simulator.
On the android, if a click is done on the label or on the imageview, that gives an : "uncaught TypeError: Cannot Read property..."
On iphone, that just don't launch anything.
If i click somewhere else (still into the view item) but not on image or on the labal, for example on an edge, that works just perfect!!
here is the code:
function menuIcons(itemTab) {
var menuMain = Ti.UI.createView({
layout : 'vertical',
backgroundColor : '#333333',
height : 125,
bottom : 10,
left : 10,
right : 10,
borderRadius : 5.0
});
var menuFirstLine = Ti.UI.createScrollView({
scrollType : 'horizontal',
contentHeight : 120,
contentWidth : 'auto',
layout : 'horizontal',
height : 120,
marginLeft : 5
});
var items = [];
var menuIconsItem = require('view/module/menuIconsItem');
for(var i in itemTab) {
var page = itemTab[i].page;
items[i] = new menuIconsItem(itemTab[i]);
(function(itemsEvent) {
itemsEvent.id = itemTab[i].id;
itemsEvent.addEventListener('click', function(e) {
Ti.App.fireEvent('main_menu_' + itemsEvent.id, {
id : e.source.id
});
})
})(items[i]);
menuFirstLine.add(items[i]);
}
menuMain.add(menuFirstLine);
return menuMain;
}
module.exports = menuIcons;
and the code of the items that is required (var menuIconsItem = require('view/module/menuIconsItem');) :
function menuIconsItem(item) {
// path for images on Android besoin de centraliser tout ca
var pathImages = '';
var itemImage = Ti.UI.createImageView({
image : item.imageLink,
width : 64,
height : 64,
top : 15
});
var itemLabel = Ti.UI.createLabel({
color : '#afafaf',
text : item.text,
font : {
textAlign : 'center'
},
height : 40,
top : 80
});
var menuItem = Ti.UI.createView({
width : 120,
height : 120,
backgroundColor : '#424242',
top : 5,
left : 5
});
menuItem.add(itemImage);
menuItem.add(itemLabel);
return menuItem;
}
module.exports = menuIconsItem;
You have to set the id for the label and image view as well.

Resources