I am trying to create a simple effect for my application which is to Fade it in from white over a period of 1-2 seconds so that the user doesn't have to see it being assembled.
I almost have it working, but there is some flickering that I can't seem to get rid of. Basically ExtJS is rendering my UI and then immediately hiding it so it can be faded in.
Here's my app:
Ext.application({
name : 'MyApp', // Application level namespace
appFolder : 'js/myapp', // Directory path to app
autoCreateViewport : true,
launch : function() {
// fade in the viewport
var form = Ext.ComponentQuery.query("viewport")[0];
form.getEl().fadeIn({
from : {
opacity : 0
},
duration : 1000
});
}
});
What can I do to get rid of the initial draw before the FadeIn?
Took a wild guess that I could set the opacity of the viewport to 0 by default and it worked:
Ext.define('MyApp.view.Viewport', {
extend : 'Ext.container.Viewport',
style: 'opacity: 0;',
items : [ {
xtype : 'someview'
} ]
});
Related
I'm trying to use cytoscape.js to display a graph on my page and I'm having a hard time just getting a basic instance to display properly.
Code Breakdown:
I get the graph elements via an AJAX call, pass the elements into the cytoscape constructor, and display the instance in a Bootstrap modal.
Here's my JavaScript:
var cy;
$.ajax({
url : "getGraphElements",
data : {
str : variableToGetCorrectGraphData
},
success : function(data) {
var elementsJson = JSON.parse(data.elements);
console.log(elementsJson);
cy = cytoscape({
container : document.getElementById('cy'),
wheelSensitivity : 0.25,
elements : elementsJson,
style : [
{
selector: 'node',
style:
{
'background-color' : '#666',
label : 'data(id)'
}
},
{
selector: 'edge',
style:
{
'width' : 3,
'line-color' : '#737373',
'target-arrow-color' : '#737373',
'target-arrow-shape' : 'triangle',
'curve-style' : 'bezier'
}
}
],
layout : {
name: 'grid',
fit: true, // whether to fit the viewport to the graph
padding: 0, // padding used on fit
avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space
avoidOverlapPadding: 20, // extra spacing around nodes when avoidOverlap: true
nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm
condense: false, // uses all available space on false, uses minimal space on true
sort: function(a,b) { // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }
return a.degree() - b.degree();
},
animate: false, // whether to transition the node positions
transform: function (node, position ){ return position; } // transform a given node position. Useful for changing flow direction in discrete layouts
}
});
$('#cyModal').modal('show');
}
});
});
Here's my Bootstrap Modal :
<div class="modal fade bd-example-modal-lg" id="cyModal" tabindex="-1" role="dialog" aria-labelledby="cyModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span> </button>
<h4 class="modal-title" id="cyModalLabel">Graph View</h4>
</div>
<div class="modal-body">
<div id="cy" style="height : 750px"></div>
</div>
</div>
</div>
</div>
And here's a sample of the JSON returned by the AJAX (although I'm almost certain this is not incorrect because all the elements appear to be present in the constructed graph) :
{ "nodes" : [{ "data" : { "id" : "12293"} }...], "edges" : [{ "data" : { "id" : "24607-26336", "source" : "24607", "target" : "26336" } }...] }
My Problem is that all the nodes appear stacked in the top left corner when the graph finishes initializing. I believe this is because the instance is using the null layout. A quick peek in the inspector console shows that cy.layout.name = 'layout'.
I just can't get it to initialize with the grid layout like I want it to. I've tried taking out the layout in the constructor, and using cy.layout({name : 'grid',}).run();. I've tried using both, one after the other. I've even tried putting cy.layout({name : 'grid',}).run(); in a while loop until cy.layout.name == 'grid' - that just caused the page to freeze. I've tried changing basically every option in both the Cytoscape initializer and the Layout initializer - no dice. What I find weird is that when I execute cy.layout({name : 'grid',}).run(); in the inspector console, the layout sets up properly...
If anyone has any ideas I'd greatly appreciate it!
Ok, OP here. I think my problem is with Bootstrap.
I started by noticing that I call $('#cyModal').modal('show'); after I've finished initializing the Cytoscape instance. I realized that before I call $('#cyModal').modal('show'); the div container for my Cytoscape instance has no size and is invisible. So I tried calling $('#cyModal').modal('show'); before initializing Cytoscape, but that still didn't work. Furthermore, I noticed that the modal wasn't actually showing until after Cytoscape initialized.
Apparently, for this sort of thing, I need to wait for the Bootstrap modal to fire the 'shown' event before setting my Cytoscape layout to be sure that the div is visible and has a size. So I put my layout setter in a listener for shown.bs.modal:
$('#cyModal').on('shown.bs.modal', function (e) {
cy.layout({
name: 'grid',
fit: true, // whether to fit the viewport to the graph
padding: 0, // padding used on fit
avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space
avoidOverlapPadding: 20, // extra spacing around nodes when avoidOverlap: true
nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm
condense: false, // uses all available space on false, uses minimal space on true
sort: function(a,b) { // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }
return a.degree() - b.degree();
},
animate: false, // whether to transition the node positions
transform: function (node, position ){ return position; } // transform a given node position. Useful for changing flow direction in discrete layouts
}).run();
});
This works for me, but it feels a bit like a hack - why can't I just do it like I originally wanted to? If that's just the way the cookie crumbles with Cytoscape.js and Bootstrap - c'est la vie; but I'll take any other suggestions if anyone has a more 'natural feeling' solution.
I'm setting up a custom zoom button and want to implement it. For some reason my defaults aren't applying to the popup.
I've tried including the out of the box structure, but to no avail.
jQuery(function($) {
$(document).ready(function() {
// Create template for zoom button
$.fancybox.defaults.tpl.zoom = '<button class="fancybox-button fancybox-zoom"><div class="zoom"><span class="zoom-inner"></span></div></button>';
// Choose what buttons to display by default
$.fancybox.defaults.buttons = [
'fullScreen',
'thumbs',
'zoom',
'close'
];
$( '.fancybox' ).fancybox({
onInit : function( instance ) {
// Make zoom icon clickable
instance.$refs.toolbar.find('.fancybox-zoom').on('click', function() {
if ( instance.isScaledDown() ) {
instance.scaleToActual();
} else {
instance.scaleToFit();
}
});
}
});
});});
Expected results is an understanding of how to implement the new zoom as well as other buttons.
The first step would be to learn to debug the code. Hit F12 to open developer tools and check Console tab. You will see this JS error message:
Uncaught TypeError: Cannot set property 'zoom' of undefined
And the reason is that you have used tpl instead of btnTpl property, so, replace that and it will work fine - https://codepen.io/anon/pen/OYaxeb?editors=1010
btw, you could also use $.extend() to tweak defaults:
$.extend(true, $.fancybox.defaults, {
btnTpl : {
// Create template for zoom button
zoom : '<button class="fancybox-button fancybox-zoom"><div class="zoom"><span class="zoom-inner"></span></div></button>'
},
// Choose what buttons to display by default
buttons : [
'fullScreen',
'thumbs',
'zoom',
'close'
]
});
I'm using Ember and Liquid Fire to create some interesting material-design-inspired animated transitions between routes.
I've created two transitions. The first occurs during the transition from the index route to the about route and uses the explode, flyTo, and toLeft transitions successfully. Here I match by a data-nav attribute on both routes to create a smooth, seamless transition that makes the matched element appear to move across the screen to the next page as it flies left. Thumbs up!
The second occurs during the transition from the about route back to the index route. Here I match a different element than above by a data-text attribute on both routes, however unlike the example above, the elements are not identical. Specifically, the font-size is different. Unfortunately this has an undesired effect of immediately displaying the larger font-size text and then having it fly across the page.
What I'd like to do is add an additional transition that animates the font-size. Sounds simple enough.
Below is my initial transitions.js file with the two transitions described above.
export default function() {
var duration = 1000;
this.transition(
// --------------------- INDEX to ABOUT ----------------------------------- //
this.fromRoute('index'),
this.toRoute('about'),
this.use('explode', {
matchBy: 'data-nav',
use: [ 'flyTo', { duration } ]
}, {
use: [ 'toLeft', { duration } ]
}),
// --------------------- ABOUT to INDEX ----------------------------------- //
this.reverse('explode', {
matchBy: 'data-text',
use: [ 'flyTo', { duration } ]
}, {
use: [ 'toRight', { duration } ]
})
);
}
I believe the answer is to create my own custom transition, however it is turning out to be rather challenging. I created a custom transition called scale-font.js and added it to my transitions.js file for this transition.
import { animate, Promise } from "liquid-fire";
export default function scaleFont(opts={}) {
// returns a Promise that resolves when the transition is done
if (!this.newElement) {
return Promise.resolve();
} else if (!this.oldElement) {
this.newElement.css({visibility: ''});
return Promise.resolve();
}
var oldFontSize = this.oldElement.css('font-size');
var newFontSize = (opts.selector ? this.newElement.find(opts.selector) : this.newElement).css('font-size');
this.newElement.css({ visibility: 'hidden' });
return animate(
this.oldElement,
{ fontSize: oldFontSize },
{ duration: 1000 }
).then(() => {
return animate(
this.newElement,
{ fontSize: newFontSize },
{ duration: 1000, visibility: 'visible' }
);
});
}
Unfortunately this doesn't quite work. The first problem is that the oldFontSize is not correct. It ends up grabbing the new font size. The second problem is no font scaling occurs.
I've researched animating fonts, so I am fairly certain it can be done. Suggestions?
I have a problem.
I have a list of tweets to show in a page. For mobile devices I don't want to show the right vertical scrollbar.
I've build the page, with its slider and its tweets list. Then I put this page in a scroll container.
Then I return the scroll container.
The code is this:
sap.ui.jsview("ttest.initView", {
/** Specifies the Controller belonging to this View.
* In the case that it is not implemented, or that "null" is returned, this View does not have a Controller.
* #memberOf ttest.initView
*/
getControllerName : function() {
return "ttest.initView";
},
/** Is initially called once after the Controller has been instantiated. It is the place where the UI is constructed.
* Since the Controller is given to this method, its event handlers can be attached right away.
* #memberOf ttest.initView
*/
createContent : function(oController) {
var oTweetList = new sap.m.List("items", {
threshold: 2,
inset : false,
showUnread : true,
scrollToLoad : true,
columns : [
new sap.m.Column({
styleClass : "data",
hAlign : "Left",
})
]
});
var oSlider = new sap.m.Slider({
id: "tweetSlider",
width: '100%',
min: 0,
change : function(oEvent){
//Update tweet list
var startIndex = 0;
var endIndex = this.getValue();
oController.updateTweetList("update", startIndex, endIndex);
}
});
var oPage = new sap.m.Page({
title: "Tweet list for #matteorenzi",
enableScrolling : false,
headerContent: [
new sap.m.Button({
icon: "sap-icon://refresh",
press : function(oEvent){
//Update tweet list with all tweets
oController.updateTweetList("first", "", "");
}
})
],
content: [
oSlider,
oTweetList
]
});
var oScroller = new sap.m.ScrollContainer({
vertical : true,
horizontal : false,
content : [
oPage
]
});
oEventBus.subscribe("it.besolution.PopulateList", "Go", function(chId, evId, data){
var template = new sap.m.ColumnListItem({
type : "Navigation",
cells : [
new it.besolution.Tweet({
user : "{user/name}",
username : "{user/screen_name}",
tweet : "{text}",
press : function(oEvent){
var path = this.getBindingContext().getPath();
sap.ui.getCore().byId("iduserDetails").setModel(oGlobalModel).bindElement(path);
app.to("iduserDetails");
}
})
]
});
oSlider.setMax(oGlobalModel.getProperty("/size") - 1);
oTweetList.setModel(oGlobalModel);
oTweetList.bindAggregation("items", "/tweets/", template);
});
return oScroller;
}
});
The page didn't load. I don't know how to do. Why the list is invisible?
Obviously, if I remove the scroll container and I return the oPage element, the list is visible.
Why? How I have to write my code to show the list without the scrollbar?
If you don't want to show the right vertical scrollbar. There is a property called enableScrolling.And you really want to use ScrollContainer, put it as Page content, not the other way around.
enableScrolling default: true
Whether the Page takes special measures to make page content scrollable and keep headers fixed. If set to false, there will be no scrolling at all; for performance reasons this is highly recommended when scrolling is not needed. The Page only allows vertical scrolling because horizontal scrolling is discouraged in general for full-page content. If it still needs to be achieved, disable the Page scrolling and use a ScrollContainer as full-page content of the Page. This allows you to freely configure scrolling. It can also be used to create horizontally-scrolling sub-areas of (vertically-scrolling) Pages.
I have an object that creates a slideshow:
Banner = SlideShowScroller.create({
height : 300,
auto : true,
navigation : {
color : "#000",
},
slides : [
{ image : "/images/1.jpg" },
{ image : "/images/2.jpg" },
]
});
How do I insert a new "slides" entry?
{ image : "/images/3.jpg" },
Is there a way to add an array to populate the slides?
It looks like the js Object you created has a field "slides" which is an array of js Objects
I would try this:
Banner.slides.push({ image : "/images/3.jpg" });
additionaly, you can use chrome element inspector (or firebug in firefox) with the break point to look at the structure of "Banner". Once you figured how to access the field "slides" I think you can just push your new image Object