how to make qooxdoo effects work? - effects

I'm trying figure out how to make something like this work:
qx.Class.define("effects.Application",
{
extend : qx.application.Standalone,
members :
{
main : function()
{
// Call super class
this.base(arguments);
// Enable logging in debug variant
if (qx.core.Environment.get("qx.debug"))
{
// support native logging capabilities, e.g. Firebug for Firefox
qx.log.appender.Native;
// support additional cross-browser console. Press F7 to toggle visibility
qx.log.appender.Console;
}
var button = new qx.ui.form.Button("First Button");
var fadeToggle = new qx.fx.effect.core.Fade(button.getContainerElement().getDomElement());
fadeToggle.set({
from : 1.0,
to : 0.0
});
var doc = this.getRoot();
doc.add(button);
button.addListener("execute", function() {
fadeToggle.start();
},this);
}
}
});
This is the entire Application.js
Just trying to do an effect on something without luck.. It's like qooxdoo is ignoring the effects

The problem is the DOM element. As you execute
button.getContainerElement().getDomElement()
it has not yet appeared in the DOM tree. So the return value of the function is null. Qooxdoo has a rendering queue, so the manifestation of what you do in the program is mostly delayed a bit. Use the 'appear' event to work around this:
var button = new qx.ui.form.Button("First Button").set({
enabled: false
});
var doc = this.getRoot();
button.addListener('appear',function(){
var fadeToggle = new qx.fx.effect.core.Fade(
button.getContainerElement().getDomElement()
).set({
from : 1.0,
to : 0.0
});
button.addListener('execute',function(){
fadeToggle.start();
});
button.setEnabled(true);
});
The bit with disabling and enabling the button is just to show off ... it will be so fast that no one will notice.
There are also several *.flush() methods in the framework where you can force the rendering to happen immediately, so calling them (the right ones :-)) might also be an option ... but since JS should be written asynchronously whenever possible, the above is probably the right thing todo.

You also might want to look at
the corresponding manual page
the code of the animation demos, e.g. this (although I concede they mostly hoook the animation to user actions)

Related

Kendo layouts not rendering widgets without setTimeout

I upgraded the kendo library to the 2014Q1 framework which had a few nice features that they were adding, however when I did that it broke any widget (grid, tabStrip, select lists, etc.) from rendering at all. I tracked it down to the layout/view not being able to activate the widget without being wrapped in a setTimeout set to 0. Am I missing something key here or did I build this thing in an invalid way?
http://jsfiddle.net/upmFf/
The basic idea of the problem I am having is below (remove the comments and it works):
var router = new kendo.Router();
var mainLayout = new kendo.Layout($('#mainLayout').html());
var view = new kendo.View('sample', {
wrap: false,
model: kendo.observable({}),
init: function() {
// setTimeout(function(){
$("#datepicker").kendoDatePicker();
// }, 0);
}
});
mainLayout.render('#container');
router.route('/', function() {
mainLayout.showIn('#app', view);
});
router.start();
Admittedly, I don't fully understand it, but hope this helps.
Basically when you try to init the #datepicker, the view elements have not been inserted into the DOM yet. You can put a breakpoint inside the init function, when it hits, check the DOM and you will see that the #app is an empty div, and #datepicker does not exist yet (at least not on the DOM).
kendo.Layout.showIn seems to need to exit in order for the view to finish rendering, but when it initializes the view's elements, it thinks the render is done and init is triggered incorrectly ahead of time. The setTimeout works because it runs the kendoDatePicker initialization asynch, the view is able to finish rendering before the timeout function.
Workarounds...
Trigger the view rendering from the view object itself:
var view = new kendo.View('sample', {
init: function() {
$("#datepicker").kendoDatePicker();
}
});
router.route('/', function() {
view.render('#app');
});
Select and find the datepicker from the view object itself:
var view = new kendo.View('sample', {
init: function() {
view.element.find("#datepicker").kendoDatePicker();
}
});
router.route('/', function() {
mainLayout.showIn('#app', view);
});
Near the bottom of this thread is where I got the idea for the 2nd option. Maybe someone else can come around and give a better explanation of whats going on.

Twitter Bootstrap Modal Form: How to drag and drop?

I would like to be able to move around (on the greyed-out background, by dragging and dropping) the modal form that is provided by Bootstrap 2. Can anyone tell me what the best practice for achieving this is?
The bootstrap doesn't come with any dragging and dropping functionality by default, but you can add a little jQuery UI spice into the mix to get the effect you're looking for. For example, using the draggable interaction from the framework you can target your modal ID to allow it to be dragged around within the modal backdrop.
Try this:
JS
$("#myModal").draggable({
handle: ".modal-header"
});
Demo, edit here.
Update: bootstrap3 demo
Whatever draggable option you go for, you might want to turn off the *-transition properties for .modal.fade in bootstrap’s CSS file, or at least write some JS that temporarily disables them during dragging. Otherwise, the modal doesn’t drag exactly as you would expect.
You can use a little script likes this.
simplified from Draggable without jQuery UI
(function ($) {
$.fn.drags = function (opt) {
opt = $.extend({
handle: "",
cursor: "move"
}, opt);
var $selected = this;
var $elements = (opt.handle === "") ? this : this.find(opt.handle);
$elements.css('cursor', opt.cursor).on("mousedown", function (e) {
var pos_y = $selected.offset().top - e.pageY,
pos_x = $selected.offset().left - e.pageX;
$(document).on("mousemove", function (e) {
$selected.offset({
top: e.pageY + pos_y,
left: e.pageX + pos_x
});
}).on("mouseup", function () {
$(this).off("mousemove"); // Unbind events from document
});
e.preventDefault(); // disable selection
});
return this;
};
})(jQuery);
example : $("#someDlg").modal().drags({handle:".modal-header"});
Building on previous answers utilizing jQuery UI, this, included once, will apply to all your modals and keep the modal on screen, so users don't accidentally move the header off screen so they can no longer access the handle. Also sets the cursor to 'move' for better discoverability.
$(document).on('shown.bs.modal', function(evt) {
let $modal = $(evt.target);
$modal.find('.modal-content').draggable({
handle: ".modal-header",
containment: $modal
});
$modal.find('.modal-header').css('cursor', 'move')
});
evt.target is the .modal which is the translucent overlay behind the actual .modal-content.
jquery UI is large and can conflict with bootstrap.
An alternative is DragDrop.js: http://kbjr.github.io/DragDrop/index.html
DragDrop.bind($('#myModal')[0], {
anchor: $('#myModal .modal-header')
});
You still have to deal with transitions, as #user535673 suggests. I just remove the fade class from my dialog.

can't tap on item in google autocomplete list on mobile

I'm making a mobile-app using Phonegap and HTML. Now I'm using the google maps/places autocomplete feature. The problem is: if I run it in my browser on my computer everything works fine and I choose a suggestion to use out of the autocomplete list - if I deploy it on my mobile I still get suggestions but I'm not able to tap one. It seems the "suggestion-overlay" is just ignored and I can tap on the page. Is there a possibility to put focus on the list of suggestions or something that way ?
Hope someone can help me. Thanks in advance.
There is indeed a conflict with FastClick and PAC. I found that I needed to add the needsclick class to both the pac-item and all its children.
$(document).on({
'DOMNodeInserted': function() {
$('.pac-item, .pac-item span', this).addClass('needsclick');
}
}, '.pac-container');
There is currently a pull request on github, but this hasn't been merged yet.
However, you can simply use this patched version of fastclick.
The patch adds the excludeNode option which let's you exclude DOM nodes handled by fastclick via regex. This is how I used it to make google autocomplete work with fastclick:
FastClick.attach(document.body, {
excludeNode: '^pac-'
});
This reply may be too late. But might be helpful for others.
I had the same issue and after debugging for hours, I found out this issue was because of adding "FastClick" library. After removing this, it worked as usual.
So for having fastClick and google suggestions, I have added this code in geo autocomplete
jQuery.fn.addGeoComplete = function(e){
var input = this;
$(input).attr("autocomplete" , "off");
var id = input.attr("id");
$(input).on("keypress", function(e){
var input = this;
var defaultBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(37.2555, -121.9245),
new google.maps.LatLng(37.2555, -121.9245));
var options = {
bounds: defaultBounds,
mapkey: "xxx"
};
//Fix for fastclick issue
var g_autocomplete = $("body > .pac-container").filter(":visible");
g_autocomplete.bind('DOMNodeInserted DOMNodeRemoved', function(event) {
$(".pac-item", this).addClass("needsclick");
});
//End of fix
autocomplete = new google.maps.places.Autocomplete(document.getElementById(id), options);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
//Handle place selection
});
});
}
if you are using Framework 7, it has a custom implementation of FastClicks. Instead of the needsclick class, F7 has no-fastclick. The function below is how it is implemented in F7:
function targetNeedsFastClick(el) {
var $el = $(el);
if (el.nodeName.toLowerCase() === 'input' && el.type === 'file') return false;
if ($el.hasClass('no-fastclick') || $el.parents('.no-fastclick').length > 0) return false;
return true;
}
So as suggested in other comments, you will only have to add the .no-fastclick class to .pac-item and in all its children
I was having the same problem,
I realized what the problem was that probably the focusout event of pac-container happens before the tap event of the pac-item (only in phonegap built-in browser).
The only way I could solve this, is to add padding-bottom to the input when it is focused and change the top attribute of the pac-container, so that the pac-container resides within the borders of the input.
Therefore when user clicks on item in list the focusout event is not fired.
It's dirty, but it works
worked perfectly for me :
$(document).on({
'DOMNodeInserted': function() {
$('.pac-item, .pac-item span', this).addClass('needsclick');
}
}, '.pac-container');
Configuration: Cordova / iOS iphone 5

Mobile Safari: Disable scrolling pages "out of screen"

I want to block scrolling page "out of the iPhone screen" (when gray Safari's background behind the page border is visible). To do this, I'm cancelling touchmove event:
// Disables scrolling the page out of the screen.
function DisableTouchScrolling()
{
document.addEventListener("touchmove", function TouchHandler(e) { e.preventDefault(); }, true);
}
Unfortunately, this also disables mousemove event: when I tap on a button then move my finger out of it, then release the screen, the button's onclick event is triggered anyway.
I've tried mapping touch events on mouse events, as desribed here: http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/, but to no avail (the same behavior).
Any ideas?
From what I understand of your question, you've attempted to combine the code you've presented above with the code snippet provided by Ross Boucher on Posterous. Attempting to combine these two snippets back-to-back won't work, because in disabling touchmove, you've also disabled the shim that allows mousemove to work via his sample.
This question and its answers sketch out a workable solution to your problem. You should try these two snippets to see if they resolve your issue:
This snippet, which disables the old scrolling behavior:
elementYouWantToScroll.ontouchmove = function(e) {
e.stopPropagation();
};
Or this one, from the same:
document.ontouchmove = function(e) {
var target = e.currentTarget;
while(target) {
if(checkIfElementShouldScroll(target))
return;
target = target.parentNode;
}
e.preventDefault();
};
Then, drop in the code on Posterous:
function touchHandler(event)
{
var touches = event.changedTouches,
first = touches[0],
type = "";
switch(event.type)
{
case "touchstart": type = "mousedown"; break;
case "touchmove": type="mousemove"; break;
case "touchend": type="mouseup"; break;
default: return;
}
//initMouseEvent(type, canBubble, cancelable, view, clickCount,
// screenX, screenY, clientX, clientY, ctrlKey,
// altKey, shiftKey, metaKey, button, relatedTarget);
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1,
first.screenX, first.screenY,
first.clientX, first.clientY, false,
false, false, false, 0/*left*/, null);
first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
And that should do it for you. If it doesn't, something else isn't working with Mobile Safari.
Unfortunately I haven't had the time to check out to above yet but was working on an identical problem and found that the nesting of elements in the DOM and which relation you apply it to affects the handler a lot (guess the above solves that, too - 'var target = e.currentTarget').
I used a slightly different approach (I'd love feedback on) by basically using a class "locked" that I assign to every element which (including all its children) i don't want the site to scroll when someone touchmoves on it.
E.g. in HTML:
<header class="locked">...</header>
<div id="content">...</div>
<footer class="locked"></div>
Then I have an event-listener running on that class (excuse my lazy jquery-selector):
$('.ubq_locked').on('touchmove', function(e) {
e.preventDefault();
});
This works pretty well for me on iOs and Android and at least gives me the control to not attach the listener to an element which I know causes problems. You do need to watch your z-index values by the way.
Plus I only attach the listener if it is a touch-device, e.g. like this:
function has_touch() {
var isTouchPad = (/hp-tablet/gi).test(navigator.appVersion);
return 'ontouchstart' in window && !isTouchPad;
}
This way non-touch devices will not be affected.
If you don't want to spam your HTML you could of course just write the selectors into an array and run through those ontouchmove, but I would expect that to be more costly in terms of performance (my knowledge there is limited though). Hope this can help.

jquery selection with .not()

I have some troubles with jQuery.
I have a set of Divs with .square classes. Only one of them is supposed to have an .active class. This .active class may be activated/de-activated onClick.
Here is my code :
jQuery().ready(function() {
$(".square").not(".active").click(function() {
//initialize
$('.square').removeClass('active');
//activation
$(this).addClass('active');
// some action here...
});
$('.square.active').click(function() {
$(this).removeClass('active');
});
});
My problem is that the first function si called, even if I click on an active .square, as if the selector was not working. In fact, this seems to be due to the addClass('active') line...
Would you have an idea how to fix this ?
Thanks
Just to give something different from the other answers. Lonesomeday is correct in saying the function is bound to whatever they are at the start. This doesn't change.
The following code uses the live method of jQuery to keep on top of things. Live will always handle whatever the selector is referencing so it continually updates if you change your class. You can also dynamically add new divs with the square class and they will automatically have the handler too.
$(".square:not(.active)").live('click', function() {
$('.square').removeClass('active');
$(this).addClass('active');
});
$('.square.active').live('click', function() {
$(this).removeClass('active');
});
Example working: http://jsfiddle.net/jonathon/mxY3Y/
Note: I'm not saying this is how I would do it (depends exactly on your requirement) but it is just another way to look at things.
This is because the function is bound to elements that don't have the active class when you create them. You should bind to all .square elements and take differing actions depending on whether the element has the class active:
$(document).ready(function(){
$('.square').click(function(){
var clicked = $(this);
if (clicked.hasClass('active')) {
clicked.removeClass('active');
} else {
$('.square').removeClass('active');
clicked.addClass('active');
}
});
});