Polymer JS - Parametric neon-animation config - javascript

I have a component - floating digit that animates from bottom to top.
And this code is working perfectly fine:
<dom-module id="floating-digit">
<style>
span.increment {
display: none;
font-size: 12px;
font-weight: normal;
position: absolute;
right: -10px;
top: 1.25em;
}
</style>
<template>
<span id="floater" class="increment">+[[digit]]</span>
</template>
</dom-module>
<script>
Polymer({
is: "floating-digit",
behaviors: [Polymer.NeonAnimationRunnerBehavior],
properties: {
digit: {
type: String,
value: "",
observer: '_animateDigit'
},
transformFrom: {
type: String,
value: "translateY(0)"
},
transformTo: {
type: String,
value: "translateY(-100%)"
},
animationConfig: {
value: function () {
return {
'animate': [
{
name: 'fade-in-animation',
node: this.$.floater,
timing: {duration: 100}
},
{
name: 'transform-animation',
node: this.$.floater,
transformFrom: "translateY(0)",
transformTo: "translateY(-100%)",
timing: {duration: 1500}
},
{
name: 'fade-out-animation',
node: this.$.floater,
timing: {duration: 2000, delay: 2000}
},
]
}
}
}
},
listeners: {
'neon-animation-finish': '_onNeonAnimationFinish'
},
_animateDigit: function _animateDigit() {
this.$.floater.style.display = "inline";
this.playAnimation('animate');
},
_onNeonAnimationFinish: function _onNeonAnimationFinish() {
this.$.floater.style.display = 'none';
},
})
</script>
But there are several places on my app where I want to use this component with different transformFrom and transformTo values.
That is why I added to my floating-digit properties transformTo and transformFrom, so I can parametrize them when I want those values to be different than default:
<floating-digit id="floating-0" transform-from="translateY(-20%)" transform-to="translateY(-80%)" digit="[[someNumber]]"></floating-digit>
I have changed animationConfig this way (only changed excerpt):
{
name: 'transform-animation',
node: this.$.floater,
transformFrom: this.transformFrom,
transformTo: this.transformTo,
timing: {duration: 1500}
},
But it does not work. This function seems not to have access to all those properties defined in element.
console.log(this) inside function returning animationConfig object value properly identifies this as desired instance of <floating-digit>. Unfortunately, without properties that can be used for parametrizing configuration of animations. They remain undefined.
Any of you possibly have an idea how to access those parameters?

If anyone is interested I have found solution. Unfortunately this solution does not use Polymer to grab those parameters.
I am using native web API to do this:
My animationConfig looks that way:
animationConfig: {
value: function () {
let transformFrom = this.attributes.getNamedItem('transform-from') ? this.attributes.getNamedItem('transform-from').textContent : "translateY(0)";
let transformTo = this.attributes.getNamedItem('transform-to') ? this.attributes.getNamedItem('transform-to').textContent : "translateY(-100%)";
return {
'animate': [
{
name: 'fade-in-animation',
node: this.$.floater,
timing: {duration: 100}
},
{
name: 'transform-animation',
node: this.$.floater,
transformFrom: transformFrom,
transformTo: transformTo,
timing: {duration: 1500}
},
{
name: 'fade-out-animation',
node: this.$.floater,
timing: {duration: 2000, delay: 2000}
},
]
}
}
}
And I am calling this same way as before:
<floating-digit id="floating-0" transform-from="translateY(-20%)" transform-to="translateY(-70%)" digit="5"></floating-digit>
If anyone have idea why this does not work properly, you are more than invited to share your solution.

Related

How to mutate VueJS prop?

Hi i'm having trouble understanding how to mutate a prop value in vue js. I'm using vue-chartjs to dynamically rerender a chart using chartjs. The behaviour works but I get a console message warning when I fire off the updateValues() function.
Vue warn]: Avoid mutating a prop directly since the value will be
overwritten whenever the parent component re-renders. Instead, use a
data or computed property based on the prop's value. Prop being
mutated: "myData"
How do I properly mutate the prop?
// Parent Component
<bar-graph :myData="dataCollection" :height="250"></bar-graph>
data () {
return {
dataCollection: {
labels: [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017],
datasets: [
{
label: 'Sample Lables',
backgroundColor: 'red',
data: [5000, 5000, 5000, 5000, 5500, 5500, 10000, 5500, 5500]
}
]
}
}
},
methods: {
updateValues () {
this.dataCollection = {
labels: [5000, 5000, 5000, 5000, 5500, 5500, 10000, 5500, 5500],
datasets: [
{
label: 'Sample Lables',
backgroundColor: 'red',
data: [5000, 5000, 5000, 5000, 5500, 5500, 10000, 5500, 5500]
}
]
}
}
}
//Child component bar graph
import { Bar } from 'vue-chartjs'
export default Bar.extend({
props: ['myData'],
mounted () {
this.renderChart(this.myData, {responsive: true, maintainAspectRatio: false})
},
watch: {
myData: function () {
console.log('destroy')
this._chart.destroy()
this.renderChart(this.myData, {responsive: true, maintainAspectRatio: false})
}
}
})
There is no way to "properly" mutate a prop, because it is a input to a component.
I recommend importing the data passed via the prop to the component's state and then using accordingly. By using this local copy, you avoid mutating the prop and getting that warning.
export default Bar.extend({
props: ['myData'],
data() {
return {
passedData: null
}
}
mounted() {
// Import data from prop into component's state
this.passedData == this.myData;
// Use as desired
this.renderChart(this.myData, {
responsive: true,
maintainAspectRatio: false
})
},
watch: {
myData: function() {
console.log('destroy')
this._chart.destroy()
this.renderChart(this.myData, {
responsive: true,
maintainAspectRatio: false
})
}
}
})
A comment / addition to #TheCascadian's answer: If myData is an Object, then this.passedData would be a reference to the same object, so you'll still get that warning. You might consider using cloneDeep from lodash to have a real inner copy of the property and use it internally accordingly.

Extjs 6 adding chart mouse listener

I am making a bar chart, and I want to so that clicking it would toggle between shortening long labels and not. However the listener does not seem to be working. I googled around and found a lot of people talking about it being a bug, however those posts are on old version (5) and I don't know if that still holds. Here is complete chart class:
Ext.define ('SenchaApp.view.barchart.BarChart', {
extend : 'Ext.chart.CartesianChart',
requires : [ 'SenchaApp.store.Personnel' ],
xtype : 'bar_chart',
reference : 'bar_chart',
itemId : 'bar_chart',
plugins: {
ptype: 'chartitemevents',
moveEvents: true
},
store : {
type : 'personnel'
},
label_length : 10,
shorten_labels : true,
flipXY : true,
axes: [{
type: 'numeric',
position: 'bottom',
fields: 'phone',
title: {
text: 'Inventory',
fontSize: 15
},
grid: {
odd: {
fillStyle: 'rgba(255, 255, 255, 0.06)'
},
even: {
fillStyle: 'rgba(0, 0, 0, 0.03)'
}
},
}, {
type: 'category',
position: 'left',
title: {
text: 'People',
fontSize: 15
},
fields: 'name',
label : {
hidden : false
},
renderer : function (axis, data) {
var str = data;
var chart = axis.getChart();
if (str.length > chart.label_length && chart.shorten_labels) {
str = str.substring(0, chart.label_length-1)+"...";
}
return str;
},
style: {
estStepSize : 1
}
}],
series: {
type: 'bar',
xField: 'name',
yField: 'phone',
listeners: {
itemtap : function(series) {
var chart = series.getChart();
alert('mouse down event');
chart.shorten_labels = !chart_shorten_labels;
}
}
},
initComponent : function () {
this.callParent(arguments);
this.axes[1].override_label_bbox (true, 2);
}
})
First step if a listener doesn't work as expected: read the listener docs carefully:
Fires when a tap event occurs on a series item. Note: This event requires the Ext.chart.plugin.ItemEvents plugin be added to the chart.
Second step is a look in the Sencha code to find the following:
chart.addElementListener({
click: handleEvent,
dblclick: handleEvent,
mousedown: handleEvent,
mousemove: handleEvent,
mouseup: handleEvent,
mouseover: handleEvent,
mouseout: handleEvent,
// run our handlers before user code
priority: 1001,
scope: this
});
together with
handleEvent: function (e) {
...
chart.fireEvent('item' + e.type, chart, item, e);
item.series.fireEvent('item' + e.type, item.series, item, e);
tap event isn't registered, so itemtap cannot be fired at all. If you bind to itemclick, on the other hand...
It's working!

How to Read Javascript Config Pattern?

If I want to create function to alert title name in this code, how to write function to alert it without including jwplayer library to my HTML file?
http://jsfiddle.net/fs7p0ec4/1/
jwplayer( "my_media_player" ).setup({
image: "http://example.com/poster.jpg",
title: "testHLS",
rtmp: { bufferlength: "2" },
bufferlength: "2",
width: "100%",
aspectratio : "16:9",
playlist: [{sources: [ { file: "http://example.com/playlist.m3u8" } ]}],
primary: "flash",
repeat: true,
controlbar: true,
stretching: "exactfit"
});
var jwplayerClass = function(xx){ }
jwplayerClass.prototype.setup = function(info) {
var XWP = info.playlist[0].sources[0].file;
alert(XWP); return this
};
var jwplayer = function (xx) {
return new jwplayerClass(xx);
};

enyo framework to integrate which raphael

I'm trying to integrate Raphael with enyo.js to create SVG component using Raphael instead of through enyo so i can use some of the Raphael functionality. I would like to replace the div that is rendered by default with it child component svg, i have created below jsfiddle. Can anyone help me fix it?
http://jsfiddle.net/stackit/uzjafamo/8/
Code
enyo.kind({
name: "Board",
kind: "enyo.Control",
paper: null,
create: function(){
this.inherited(arguments);
},
rendered: function(){
this.inherited(arguments);
if(this.hasNode()){
paper = Raphael(this.hasNode().id, 100, 100);
}
}
})
enyo.kind({
name: "pages",
kind: "enyo.Control",
create: function(){
this.inherited(arguments);
this.loadView();
},
loadView: function(){
if(!this.$.board){
var com = this.createComponent({
name: "board",
kind: "Board",
},{
owner: this
});
com.render();
}
}
});
new pages().renderInto(document.getElementById("cans"));
I looked at your fiddle and saw a little bit that could be improved. The jsFiddle container was giving me some trouble though initially, until I forked it for some reason.
Here's what I came up with: http://jsfiddle.net/Djspaceg/5qyLej05/4/
enyo.kind({
name: "Board",
kind: "enyo.Control",
paper: null,
create: function () {
this.inherited(arguments);
},
rendered: function () {
this.inherited(arguments);
if (this.hasNode() && !this.paper) {
this.generateRaphael();
}
},
generateRaphael: function () {
this.paper = Raphael(this.hasNode().id, 100, 100);
}
});
enyo.kind({
name: "pages",
kind: "enyo.Control",
create: function () {
this.inherited(arguments);
this.loadView();
},
loadView: function () {
if (!this.$.board) {
var com = this.createComponent({
name: "board",
kind: "Board",
});
com.render();
}
}
});
new pages().renderInto(document.getElementById("cans"));
It just generates an empty Raphael canvas.
Cheers!

ExtJS TaskRunner

I'm still in the learning process with EXTJS and any help would be much appreciated.
The goal for me is to load data into a grid where one cell needs to have the value incremented every minute. From my research using the TaskRunner function is the way to go but can't figure out where to put it and how to use it. My assumption is that it needs to go into the model or the controller but I'm not sure. In my simple project I'm using the MVC architecture.
Currently my gird works as expected. It reads in a file does a date conversion that produces a minute value. It's that minute value that I need to increment.
The code below is a sample TaskRunner snippit that I'm working with, right or wrong I don't know yet.
var runner = new Ext.util.TaskRunner();
var task = runner.newTask({
run: store.each(function (item)
{
var incReq = item.get('request') + 1;
item.set('request', incReq);
}),
interval: 60000 // 1-minute interval
});
task.start();
Model:
Ext.define("myApp.model.ActionItem", {
extend : "Ext.data.Model",
fields : [
{
name: 'pri',
type: 'int'
},
{
name: 'request',
type: 'int',
defaultValue: 0,
convert : function(v, model) {
return Math.round((new Date() - new Date(v)) / 60000);
}
}
]
});
Controller:
Ext.define("myApp.controller.HomeController", {
extend: "Ext.app.Controller",
id: "HomeController",
refs: [
{ ref: "ActionItemsGrid", selector: "[xtype=actionitemgrid]" },
{ ref: "DetailsPanel", selector: "[xtype=actionitemdetails]" }
],
pri: "",
models: ["ActionItem"],
stores: ["myActionStore"],
views:
[
"home.ActionItemDetailsPanel",
"home.ActionItemGrid",
"home.HomeScreen"
],
init: function () {
this.control({
"#homescreen": {
beforerender: this.loadActionItems
},
"ActionItemsGrid": {
itemclick: this.displayDetails
}
});
},
displayDetails: function (model, record) {
this.getDetailsPanel().loadRecord(record);
},
loadActionItems: function () {
var store = Ext.getStore("myActionStore");
store.load();
this.getActionItemsGrid().reconfigure(store);
}
});
View:
Ext.define("myApp.view.home.ActionItemGrid", {
extend: "Ext.grid.Panel",
xtype: "actionitemgrid",
resizable: true,
multiSelect: false,
enableDragDrop : false,
store: null,
columns:
[
{ header: "Pri", dataIndex: "pri", sortable: false, autoSizeColumn: true},
{ header: "Req", dataIndex: "request", sortable: false, autoSizeColumn: true}
],
viewConfig:
{
listeners: {
refresh: function(dataview) {
Ext.each(dataview.panel.columns, function(column) {
if (column.autoSizeColumn === true)
column.autoSize();
})
}
}
}
});
Sample JSON File:
{
"actionitems" : [
{
"pri": 1,
"request": "2014-12-30T03:52:48.516Z"
},
{
"pri": 2,
"request": "2014-12-29T05:02:48.516Z"
}
]
}
You have error in code which creates task - you should provide function to run configuration property, not result of invocation. Try this:
var runner = new Ext.util.TaskRunner();
var task = runner.newTask({
run: function() {
store.each(function (item)
{
var incReq = item.get('request') + 1;
item.set('request', incReq);
})
},
interval: 60000 // 1-minute interval
});
task.start();
You can put that code in loadActionItems method.

Categories

Resources