Famo.us RenderController not working under SequentialLayout? - layout

I have added a common Surface and a Scrollview (actually a FlexScrollView) to a SequentialLayout and then added the layout to my View as the following code shows:
function _createCameraView() {
var layoutViews = [];
this.cameraView = new View({
size: [undefined, this.options.footerSize]
});
var layout = new SequentialLayout({
size: [undefined, this.options.footerSize],
direction: Utility.Direction.Y
});
var backgroundSurface = new Surface({
size: [undefined, 120],
content: 'some content',
classes : ['photo-guide-content'],
properties: {
backgroundColor: 'transparent',
zIndex: 4
}
});
// detail list
var detailsList = new FlexScrollView({
layout: ListLayout,
direction: Utility.Direction.X, // set direction to horizontal
paginated: true,
//autoPipeEvents: true,
useContainer: true,
container : {
size: [undefined, 60],
properties : {
'z-index' : 5,
}
}
});
layoutViews.push(backgroundSurface);
layoutViews.push(detailsList);
layout.sequenceFrom(layoutViews);
this.cameraView.add(alignModifier).add(layout);
}
Then I've added a RenderController on another view and I'm using it to display my cameraView like this:
function _selectCamera() {
if (!this.cameraView) {
_createCameraView.call(this);
}
this.footerRender.hide(this.mapView);
this.footerRender.show(this.cameraView);
}
I know I don't need to call the hide method from the render on the function above, just the show method and it should swap the views with a smooth opacity transition, which is defined by default. Although when using this Sequential Layout I'm not getting this effect. I know it has to do with this layout because I've tried to switch the layout to a FlexibleLayout and a GridLayout, and it works fine with these two. So, my question is, why doesn't work with the SequentialLayout? I've also noticed it has a method called setOutputFunction(outputFunction), is there a way to use it so the layout uses the opacity returned from the RenderController or how can it be fixed some other way?

Try adding a getSize method to your view.
Something like this:
this.cameraView.getSize = function() {
return [undefined, undefined];
};

Related

PhaserJS: After Rotation of camera dragging a Sprite gives strange coords

Basically the problem is that after you rotate the camera, the points that are given as arguments in the callback for dragging are not what I expected. I'm guessing I have to Rotate the given points also but I just couldn't.
Can Someone explain what is going on, is this some kind of bug or what should I do in order the sprite to follow the mouse cursor?
Easiest way to explain the problem is to reproduce it:
1) Go to Phaser Example Runner
2) Copy- Paste this code:
var config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
scene: {
preload: preload,
create: create
}
};
var game = new Phaser.Game(config);
function preload ()
{
this.load.image('eye', 'assets/pics/lance-overdose-loader-eye.png');
}
function create ()
{
var image = this.add.sprite(200, 300, 'eye').setInteractive();
this.cameras.main.setRotation(Math.PI);
image.on('pointerover', function () {
this.setTint(0x00ff00);
});
image.on('pointerout', function () {
this.clearTint();
});
this.input.setDraggable(image);
this.input.on('dragstart', function (pointer, gameObject) {
gameObject.setTint(0xff0000);
});
this.input.on('drag', function (pointer, gameObject, dragX, dragY) {
console.log(`x: ${dragX}, y: ${dragY}`);
gameObject.x = dragX;
gameObject.y = dragY;
});
this.input.on('dragend', function (pointer, gameObject) {
gameObject.clearTint();
});
}
3) Open the console, drag around the Eye and look at what coordinates are given.
4) If you remove line 24 (the rotation of the camera) Everything works as expected.
(The example is taken from Phaser 3 Official examples and a bit changed for the bug)
According to Phaser's API Documentation on the setRotation() method, the rotation given in radians applies to everything rendered by the camera. Unfortunately, your pointer isn't rendered by the camera so it doesn't get the same rotated coordinates. Not sure if this is a bug with the library or just a poorly documented exception, but I believe there is a workaround.
Create 2 variables to hold an initial position and a final position:
var image = this.add.sprite(200, 300, 'eye').setInteractive();
var initial = [];
var final = [];
Populate the initial position in your .on('dragstart') method:
this.input.on('dragstart', function (pointer, gameObject) {
initial = [
gameObject.x,
gameObject.y,
pointer.x,
pointer.y
];
gameObject.setTint(0xff0000);
});
Then, populate the final variable in your .on('drag') method:
this.input.on('drag', function (pointer, gameObject, dragX, dragY) {
final = [
gameObject.x, // not necessary but keeping for variable shape consistency
gameObject.y, // not necessary but keeping for variable shape consistency
pointer.x,
pointer.y
];
gameObject.x = initial[0] + (initial[2] - final[2]);
gameObject.y = initial[1] + (initial[3] - final[3]);
});
All we're doing here is keeping track of the change in pointer position and mimicking that change in our gameObject.

How to set colors for Chart.js tooltip labels

In Chart.js I am unable to set a color for the tooltip.I want to color the label "December 2016" as same as the color of the legend (Blue).
Please see below;
graphOptions.tooltips = {
enabled: true,
mode: 'single',
displayColors: false,
callbacks: {
title: function (tooltipItem, data) {
if (tooltipItem.length > 0) {
return tooltipItem[0].xLabel + ': ' + tooltipItem[0].yLabel +" Scans";
}
return "";
},
label: function (tooltipItem, data) {
if (data.datasets.length > 0) {
return data.datasets[tooltipItem.datasetIndex].label;
}
return '';
},
labelColor: function (tooltipItem, chartInstace) {
if (data.length > 0) {
return data[tooltipItem.datasetIndex].backgroundColor;
}
}
}
};
You haven't defined anything called data in the labelColor callback function. Another confusion with this callback in charts.js, is the second parameter passed to the labelColor callback function is the chart instance, and not the datasets like some of the other chartjs callbacks.
Anyway, this should work.
labelColor: function(tooltipItem, chart) {
var dataset = chart.config.data.datasets[tooltipItem.datasetIndex];
return {
backgroundColor : dataset.backgroundColor
}
}
You might want to try with labelTextColor instead of labelColor
This is a feature available since Chartjs 2.7
https://github.com/chartjs/Chart.js/releases/tag/v2.7.0
(Feature #4199)
labelTextColor: function(tooltipItem, chart) {
if (chart.tooltip._data.datasets[tooltipItem.datasetIndex].label === "amount")
{
return "#1ff368";
}
if (chart.tooltip._data.datasets[tooltipItem.datasetIndex].label ==="transactions") {
return "#8577ec";
}
}
just type your chart label like "amount" and then modify your colors in hand
Actually, the problem is that in labelColor callback you returning the backgroundColor. Below is the right return type of above callback method.
function (tooltipItem, chartInstance) {
return {
borderColor: borderColor,
backgroundColor: backgroundColor
};
}
In backgroungColor assign the color for the label. and you can leave the borderColor.
[Sample-Code]
labelColor : function(tooltipItem, chartInstance){
return {
backgroundColor : data.datasets[tooltipItem.datasetIndex].backgroundColor[0]
};
}
Actually, if your dataset color is just an item and not an array this you shall not need an extra tooltip callback eg.
Single color intepreted as the one shown in the tooltip automatically
const myDataset = {
label: 'My dataset',
data: [1,2.3,4,-5],
fill: true,
// this will show the tooltip with red color
backgroundColor: '#e23944',
borderColor: 'blue'
}
instead of
Array of colors not intepreted as the one shown in the tooltip
const myDataset = {
label: 'My dataset',
data: [1,2.3,4,-5],
fill: true,
// need to remove the array of color here
backgroundColor: ['#e23944'],
borderColor: ['blue']
}
According to the screenshot, you have only one dataset matching one color, so you don't need to put the colors as an array. If you need to set multiples points within the same dataset using different colors, then you shall use
Array of colors distributed to each data points
const myDataset = {
label: 'My dataset',
data: [1,2.3,4,-5],
fill: true,
// need to remove the array of color here
backgroundColor: ['#e23944', '#D4E157', '#26A69A', '#758BE2'],
borderColor: ['blue', 'green', 'white', 'dark']
}
But then you shall forgot this solution ^^ and adopt the one given above ;)
PS :For border and background colors you can use hexa, rbg or string notations.
Hope it helps :)
'tooltipItem' doesn't exists, misspelling the final 's'. So, your code should be
labelColor : function(tooltipItem, chartInstance){
return {
backgroundColor : data.datasets[tooltipItems.datasetIndex].backgroundColor[0]
};
}

fabricjs IText - Clear Character Specific Styles

I need to be able to set the fontFamily for an entire IText object even if it has character specific styling (code example and jsfiddle below). Note, when changing the fontFamily the character-specific styles don't change. Is there a way for me to access and clear those styles and then apply the style to the entire set of characters?
http://jsfiddle.net/xmfw65qg/48/
var iTextSample = new fabric.IText('hello\nworld', {
styles: {
0: {
0: { textDecoration: 'underline', fontSize: 80 },
1: { textBackgroundColor: 'red' }
},
1: {
0: { textBackgroundColor: 'rgba(0,255,0,0.5)' },
4: { fontSize: 20 }
}
}
});
2020 May Edit
In later revisions of fabricJS, the method removeStyle(props) has been added.
That means you can do:
myTextObject.removeStyle('fontFamily');
to clean it up.
You also have:
myTextObject.cleanStyle('fontFamily');
That will instead remove all the fontaFamily properties that are duplicated of the main object. So that the style object is reduced in complexity if possible.
Original answer
http://jsfiddle.net/asturur/xmfw65qg/50/
you have to manually iterate the style object and clear the fontFamily property.
function setFont(name, value) {
var object = canvas.item(0);
if (!object) return;
if (object.styles) {
var styles = object.styles;
for (var row in styles) {
for (var char in styles[row]) {
if ('fontFamily' in styles[row][char]) {
delete styles[row][char]['fontFamily'];
}
}
}
}
object.set(name, value).setCoords();
canvas.renderAll();
}
why this is necessary is another matter.
I would open an issue on the github repository for that.
Edit:
As fabricjs released 1.6.2 a small bug that was causing the original style object to be changed during rendering, has been fixed.

Ext js 3.4 window add/remove Component error

We are using extjs 3.4. The purpose is to replace a component in a Ext.Window. Even if
there is no error when we remove the old and add the new component, when trying doLayout() the error
Uncaught TypeError: Cannot read property 'offsetWidth' of undefined
occurs.
The code that creates the window is:
function createWindowConf(id, winconf, items) {
var conf = {
id: id,
title: winconf.title,
iconCls: winconf.icon,
x : winconf.xpos,
y : winconf.ypos,
width : parseInt(winconf.xsize),
height : parseInt(winconf.ysize),
layout : winconf.layout, //'border',
border : false,
resizable : winconf.resizable,
manager: windows,
shadow: false,
closable: true,
items: items
};
var win = new Ext.Window(conf);
win.render(desktopEl);
return win;
};
The items are a Ext.grid.GridPanel and a Ext.form.FormPanel.
According to user's current selection in grip (component in position 0) the old form should be removed and a new should be added (component in position 1).
The code that creates the form is:
var theConfig = {
id: config.yid,
bodyStyle: 'padding:5px 5px 0',
width: 370,
maxWidth: 370,//not resizable
minWidth: 370,
layout: 'form',
margins: '0 0 0',
region: 'east',
split: true,
colapsible : true,
trackResetOnLoad: true,
autoScroll: true,
fieldDefaults: {
msgTarget: 'side',
labelWidth: 75
},
items: [],
buttons: [scopeDetails.updateButton, scopeDetails.submitButton]
};
this.detailsForm = new Ext.form.FormPanel(theConfig);
and the items added afterwards.
The code that updates (adds/removes) components from the window is:
this.updateWin = function(moduleForRemoveId, form, idWin) {
var win = this.getWindow(idWin);
if (win != null) {
win.remove(moduleForRemoveId);
win.add(form);
win.doLayout();
}
}
and produces the error in win.doLayout().
By removing all components and add the add the new ones:
win.removeAll();
win.add(this.grid);
win.add(this.form);
win.doLayout();
we have the same error.
Any suggestion will be really helpful since more than 3 days spent for that error
I'm pretty sure the error comes from something else rather than the component remove/add.
I created a simple testcase which defines a window with a form and a grid, and a button which replaces everything with a panel. And it works.
Your code is incomplete. You should provide a full example.
Have you tried to debug it yourself? Enable "pause on uncaught exceptions" on your Chrome script debugger the reproduce the bug. You will get a stack trace of what happened, giving you hints on what is wrong. Of course include ext-all-debug.

YUI3 autocomplete has images on top - How to get autocomplete to the top

My auto YUI autocomplete zindex is off. How can I force the autocomplete DIV to the top.
Below I am using a standard template for YUI:
YAHOO.util.Event.onDOMReady(function(){
YUI().use("autocomplete", "autocomplete-filters", "autocomplete-highlighters", function (Y) {
var inputNode = Y.one('#name'),
tags = [
'css',
'css3',
'douglas crockford',
'ecmascript',
'html',
'html5',
'java',
'javascript',
'json',
'node.js',
'pie',
'yui'
],
lastValue = '';
inputNode.plug(Y.Plugin.AutoComplete, {
activateFirstItem: true,
minQueryLength: 0,
queryDelay: 0,
source: tags,
resultHighlighter: 'startsWith',
resultFilters: ['startsWith']
});
// When the input node receives focus, send an empty query to display the full
// list of tag suggestions.
inputNode.on('focus', function () {
inputNode.ac.sendRequest('');
});
// When there are new AutoComplete results, check the length of the result
// list. A length of zero means the value isn't in the list, so reset it to
// the last known good value.
inputNode.ac.on('results', function (e) {
if (e.results.length) {
lastValue = inputNode.ac.get('value');
} else {
inputNode.set('value', lastValue);
}
});
// Update the last known good value after a selection is made.
inputNode.ac.after('select', function (e) {
lastValue = e.result.text;
});
});
});
Simply to put the z-index in the css. Setting via JS used to be allowed, but as of YUI 3.4.0 it's a css-only flag (https://github.com/yui/yui3/blob/master/src/autocomplete/HISTORY.md).
The relevant CSS is (adjust your z-index as necessary):
.yui3-aclist { z-index: 100; }
PS., your YAHOO. line is from YUI2, so that is quite peculiar and definitely not a standard template.
By the time your callback in the YUI().use(...) section is called, the dom should be ready. No ondomready required.

Resources