Titanium WebView.toImage on coverFlowView - webview

A have several views with WebViews on them. I need to make it in a coverFlowView. For that i make my views toImage, to put after on the coverFlow, but the issue is that i get images with webView not loaded... I tried to make setTimeout, but it doesn't help.
var cover = Titanium.UI.iOS.createCoverFlowView({
images: forflowImages
});
for (var k = start; k < cData.length; k++) {
r = Ti.UI.createView({});
for (var j = 0; j < child.objects.length; j++) {
tmp = Ti.UI.createWebView({
left : 10,
top : 10,
right : 10,
bottom : 10,
width : Ti.UI.FILL,
height : Ti.UI.SIZE,
willHandleTouches: true,
backgroundColor : '#fff2df',
});
tmp.html = obj.html;
no.add(tmp);
r.add(no);
}
}
r.addEventListener("load", function(e) {
blob = r.toImage();
});
forflowImages.push(blob);
}
cover.setImages(forflowImages);
With this code, coverFlowView doesn't have any views.
setTimeout(function() {
blob = r.toImage();
}, 500);
Also doesn't help, i have activity indicator on the page saved, content seems didn't have time to load before toImage function acted.

You are ordering things the wrong way, and you have multiple syntax errors, also you are listeneing for the load event on the wrong type of view, you shold be listeneing on the WebView, try this instead:
var forflowImages = [];
var container = // This should already be in the view stack somewhere
var cover = Titanium.UI.iOS.createCoverFlowView();
function loadListener(e) {
forflowImages.push(e.source.toImage());
if(forFlowImages.length == child.objects.length) {
// We have all the images for cover flow
cover.setImages(forflowImages);
}
}
var containerView = Ti.UI.createView();
for (var j = 0; j < child.objects.length; j++) {
var tmp = Ti.UI.createWebView({html : obj.html);
tmp.addEventListener("load", loadListener);
container.add(tmp);
tmp.repaint();
}
I removed some of your code that was syntactically incorrect and trimmed it down so it would be easy to understand. All this code does is add an event listener that handles the conversion of a webview to an image.

Related

AddEventListener only works with the last picture

I have one problem. addEventListener only works with the last element of the loop. I know what is the problem, but I can't figure it out. I get the JSON object from another function with the information. Later on the left side there should be clickable pictures. After clicking it I should get the same picture on the right side showed. Still it works only with the last one.
function myFunction(obj) {
var listItems = document.getElementsByClassName("newimg");
for (var i = 0; i < obj.length; i++) {
(function (i) {
document.getElementById("imgSmall").innerHTML += `<br></br><img id="${i}" class="newimg" src=${obj[i].download_url} >`;
let p = obj[i];
listItems[i].addEventListener('click', function() { makeithappen(p);},true);
}(i));
//obj[i].width,obj[i].height,obj[i].author,obj[i].download_url>
}
}
function makeithappen(k) {
document.getElementById("imgLarge").innerHTML = `<br class="text"> AUTHOR: ${k.author}, WIDTH: ${k.width}, HEIGHT: ${k.height}</br><img class="img2" src=${k.download_url} >`;
}
For quick fix.
Replace in your code
listItems[i].addEventListener('click', function() { makeithappen(p);},true);
with
listItems[i].onload = function() {
listItems[i].addEventListener('click', function () { makeithappen(p); }, true);
}
So when you got your listItems you weren't finished with the creation of more images. So new image means new list.
for (let i = 0; i < obj.length; i++) {
document.getElementById("imgSmall").innerHTML += `<br></br><img id="${i}" class="newimg" src=${obj[i].download_url}>`;
const listItems = document.getElementsByClassName("newimg");
listItems[i].addEventListener('click', function () { makeithappen(p); }, true);
}
function makeithappen(k) {
document.getElementById("imgLarge").innerHTML = `<br class="text"> AUTHOR: ${k.author}, WIDTH: ${k.width}, HEIGHT: ${k.height}</br><img class="img2" src=${k.download_url} >`;
}
Pleas do refactor <br></br> into something with css, margin or padding or whatever. This will then allow you to create the images with let div = document.createElement('img') and bind the event listener directly div.addEventlistener(...)

Get a list of pictures and upload them with CasperJS?

I need some help with my CasperJS script.
I don't know how can I get all my pictures as an array from the current folder.
And how to loop to insert each one in the correct input.
Mmmh, difficult to explain so there is my starting code.
I put comment where I have problem.
var casper = require('casper').create();
casper.start('http://imgchili.net/', function() {
// Get a list with all the picture from the current folder.
// For each picture, click this button.
this.mouseEvent('click', 'input.button1:nth-child(6)');
this.fillSelectors('form#upload_form', {
// Another loop here.
'.grey > input:nth-child(2)': /* First picture */,
'.grey > input:nth-child(4)': /* Second picture */,
'.grey > input:nth-child(6)': /* Third picture */
}, true);
casper.capture('captureTest.png');
});
// 8s can be too low if I have a lot of pictures!
casper.wait(8000, function() {
casper.capture('captureResult.png');
})
casper.then(function() {
this.echo(this.fetchText('textarea.input_field:nth-child(11)'));
})
casper.run();
EDIT:
Thanks it helps me a lot. But I have problem to loop the inputs.
var fs = require('fs'),
casper = require('casper').create(),
myImages = fs.list(fs.workingDirectory + '/img');
casper.start('http://imgchili.net/', function() {
// For each image, click to add a new upload input.
// Begin with 2 because 0 = "."" and 1 = "..".
for (var i = 2; i < myImages.length; i++) {
this.mouseEvent('click', 'input.button1:nth-child(6)');
}
// It doesn't work and show no error...
for (var i = 2; i < myImages.length; i++) {
j = i*2;
input = '.grey > input:nth-child(' + j + ')';
this.fillSelectors('form#upload_form', {
input : '/img/' + myImages[i],
}, false);
// Even this part doesn't work
console.log('i = ' + i + ' & imgName = ' + myImages[i]);
}
});
casper.then(function() {
casper.capture('result.png');
});
casper.run();
You can use PhantomJS file system to get your current folder files. Here is the API Documentation.
The following gets your current folders files, and then filters all .png's into a new array. You can then use a loop to click the button for each image. You will have to alter / add your own code because this does not accomplish the upload task. This will should help you though.
// vars
var fs = require('fs'); // reference to phantomJS file system
var myFolder = fs.list(fs.workingDirectory); // gets all files in current folder
var myImages = []; // only images from current folder
var url = 'http://imgchili.net/'; // starting url
var fileType = '.png'; // image file type to filter by
casper.then(function() {
// create array of just images
for (var i = 0; i < myFolder.length; i++) {
if (myFolder[i].indexOf(fileType) != -1) {
myImages.push(myFolder[i]);
}
}
// click for each image
for (i = 0; i < myImages.length; i++) {
this.mouseEvent('click', 'input.button1:nth-child(6)');
}
});
// wait for images to be uploaded
// set timeout or defaults to caspers step timeout
casper.waitForSelector('#page_body', function() {
casper.capture('captureResult.png');
}, 15000);

my shapes aren't changing colors I'm not sure why

I have a code that draws a bunch of customized shapes from an xml... I want to make each shape select-able /de-selectable by changing the color of the object and changing backk all other colors when things change but my codes broken but i'm not getting any errors or anything it just doesn't work.
var graphicsShape
function drawLayer(layer){
for (var i =0; i < xmlDoc.getElementsByTagName("polygon").length; i++)
{
if (layer == xmlDoc.getElementsByTagName("polygon")[i].childNodes[0].attributes[4].value)
{ drawSegment(i);
}
}
}
// layer = index z
function drawSegment(a){
var vertexList = xmlDoc.getElementsByTagName("polygon")[a].childNodes;
var graphicsObject = new createjs.Graphics();
graphicsShape = new createjs.Shape(graphicsObject);
graphicsObject.setStrokeStyle(1);
graphicsObject.beginStroke(createjs.Graphics.getRGB(0,0,0));
graphicsObject.beginFill(createjs.Graphics.getRGB(255,0,0));
for(var i = 0; i < vertexList.length; i++){
graphicsObject.lineTo(vertexList[i].attributes[2].value, vertexList[i].attributes[3].value)
stage.addChild(graphicsShape);
}
segmentsArray.push(graphicsShape);
//createContainer(segmentsArray[i]);
}
function createArraysForSegments() {
for(var i=0; i <segmentsArray.length; i++){
segmentsData[i] = new Array;
}
}
function ColorChangeAddEventListener() {
for(var i = 0; i < segmentsArray.length; i++){
segmentsArray[i].addEventListener('click', colorChange(i));
}
}
function colorChange(index){
segmentsArray[index].graphics.beginFill('white');
stage.update();
}
i call the functions later
ColorChangeAddEventListener();
drawLayer(0);
stage.update();
if i type segmentsArray[0].alpha =0.5; it works for that shape, but when I put it in segmentsArray[0].addEventsListener('click', function){segmentsArray[0].alpha=0.5;}) that doesn't work
Just setting the beginFill won't affect the current shape, you will also have to segmentsArray[index].graphics.clear() and redraw the shape.
beginFill() is not the setter for a property but rather a command that affects subsequents commands, like drawRect() for example.

add each dataLabel a function on mouseover/mouseout

I want to add each dataLabel a (just call it "highlightPoint()") function on a mouseover event. It works, if I add this function to a single point.
chartObj.series[0].data[1].dataLabel.on("mouseover", function () {
chartObj.series[0].data[1].setState('hover');
});
It doesn't work if I loop threw my data points. I guess the reference to each individual point is incorrect or something like that.
jsfiddle-link
After you have looped through both data sets, i = 2 and k = 1. So the mouse events are always trying to use i=2 and k=1 to access the data point, which of course is out of bounds. See this fiddle: http://jsfiddle.net/bLvfS/1/
for (var i = 0; i < chartObj.series.length; i++) {
for (var k = 0; k < chartObj.series[i].data.length; k++) {
var onmouseover = function(u, j) {
return function() {chartObj.series[u].data[j].setState('hover');};
}
var onmouseout = function(u, j) {
return function() {chartObj.series[u].data[j].setState();};
}
chartObj.series[i].data[k].dataLabel.on("mouseover", onmouseover(i,k));
chartObj.series[i].data[k].dataLabel.on("mouseout", onmouseout(i,k));
}
}
I've added functions that get passed the current i,k pair and return the actual function you want to run on the mouse events. Maybe someone has a better solution... but it seems to work.
Problem is with closures, see working fiddle: http://jsfiddle.net/Fusher/bLvfS/2/
for (var i = 0; i < chartObj.series.length; i++) {
for (var k = 0; k < chartObj.series[i].data.length; k++) {
(function(i,k){
chartObj.series[i].data[k].dataLabel.on("mouseover", function () {
chartObj.series[i].data[k].setState('hover');
});
chartObj.series[i].data[k].dataLabel.on("mouseout", function () {
chartObj.series[i].data[k].setState();
});
})(i,k);
}
}

Titanium ImageView animation width and height

I try to create an ImageView in Titanium like this:
var animationView = Titanium.UI.createImageView
(
{
images:animationImages,
duration:50,
repeatCount:0,
width: '90dp',
height: '270dp'
}
);
On android it gets its size as expected, but on IOS, it simply doesn't gets scaled. Is there something, i'm doing wrong? Or should i do it frame by frame by creating the ImageViews manually then changing them with setInterval?
This is actually not a consistent solution, it should be a comment, but since I don't have enough rep I have to write it as an answer.
For starters I would try to give it a top and left properties.
Secondly, are those images retrieved from a remote URL? Remote URLs are only supported in Android. If that is the case you could do a workaround as you said in the question.
Finally, the 'dp' only works for android, so it won't scale at all in iOS, it will simply erase the 'dp' and use the number as "points", on non-retina screens it will be the same number of pixels and on a retina display it will be the double.
I finally decided to create my own animation class, which look like this:
function Animation(data)
{
var width = data.hasOwnProperty("width") ? data.width : Ti.UI.SIZE;
var height = data.hasOwnProperty("height") ? data.height: Ti.UI.SIZE;
var duration = data.hasOwnProperty("duration") ? data.duration : 50;
var imageFiles = data.hasOwnProperty("images") ? data.images : [];
var images = [];
var container = Ti.UI.createView
(
{
width:width,
height: height
}
);
for(var i=0; i<imageFiles.length; i++)
{
var image = Ti.UI.createImageView
(
{
image:imageFiles[i],
width:width,
height:height
}
);
if(i!=0)
image.setVisible(false);
container.add(image);
images.push(image);
}
container.activeImage = 0;
container.intervalId = null;
container.setActiveImage = function(index)
{
if(container.intervalId == null)
container.activeImage = index;
}
container.start = function()
{
var callback = function()
{
for(var i=0; i<images.length; i++)
{
if(i == container.activeImage)
images[i].setVisible(true);
else
images[i].setVisible(false);
}
container.activeImage = (container.activeImage + 1) % images.length;
}
container.intervalId = setInterval ( callback, duration );
}
container.stop = function()
{
clearInterval(container.intervalId);
container.intervalId = null;
}
return container;
}
module.exports = Animation;
And you can use it like this:
var Animation = require('...path to your animation file');
var myAnimation = new Animation
(
{
width:'100dp',
height:'100dp',
duration:50, //duration while one frame is showing
images:['one.png', 'two.png'...], //full paths
}
);
//start:
myAnimation.start();
//stop
myAnimation.stop();

Resources