Kendo layouts not rendering widgets without setTimeout - mvvm

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.

Related

openui5 event Handler for orientationchange

Is there any openui5 event Handler for orientationchange and window resize ?
onInit: function() {
var data;
this.drawChart(data); // working fine
$( window ).resize(function() {
this.drawChart(data); // not working
});
},
drawChart: function(data) {
//code for draw chart
}
OpenUI5 has built-in functionality for detecting orientation change as well as when there is a responsive size change (desktop->tablet for example).
Take a look at sap.ui.Device.orientation's attachHandler event:
Registers the given event handler to orientation change events of the
document's window.
Here is an example of using sap.ui.Device.orientation.attachHandler:
sap.ui.Device.orientation.attachHandler(function(mParams) {
if (mParams.landscape) {
alert('in landscape mode');
} else {
alert('in portrait mode');
}
});
Also of use is sap.ui.Device.media's attachHandler for detecting when the window is resized to a different range-set.
For directly listening to when the window is resized it looks like you already have a solution for that, just make sure you keep track of the correct scope to use:
var self = this;
$( window ).resize(function() {
self.drawChart(data);
});
I found the solution
this.* will not work inside jquery as this has a different meaning wherever its encapsulated...
in openui5 *.view.js this implies the view object
in *.controller.js this implies the controller object...
in jquery this implies the component in which it is placed or whatever it is referring to in that context...
you cannot simply mix "this" wherever you like
sap.ui.controller("oui5mvc.controllerName").drawChart(data);

infinite scroll manual trigger callback

I'm using Infinite Scroll plugin in a (I know it is unrecommended http://isotope.metafizzy.co/docs/help.html#infinite_scroll_with_filtering_or_sorting), Infinite Scroll + Isotipe Filtering combination.
Now sometimes happend that after i run my filter, if I get an empty list i manually trigger infinite scroll to load more elements.
$('.items').isotope({ filter: filter }, function( $items ) {
var id = this.attr('class'),
len = $items.length;
if (len == 0){getElement();}
});
Here is my function that load elements, but it seems that the callback is not working.
function getElement(){
$('.items').infinitescroll('retrieve',function(items){
console.log('callback');
console.log(items);
});
}
Unfortunally Infinite Scroll documentation is not the best for manual trigger (it suggest a not-working way to call it - $(document).trigger('retrieve.infscr'); i found the solution here: infinite scroll manual trigger) so I'm a little bit stucked here.
Any suggestion?
I know it is a very old post. But I find it over Google as I searched for the self problem. But I also find the solution for this. Perhaps it helps somebody...
You must put the callback not to the main function. Because manual function only push the main function.
jQuery(document).ready(function($) {
var $infinitecontainer = $(".infinite-content").infinitescroll({
navSelector: ".nav-links",
nextSelector: ".nav-links a:first",
itemSelector: ".infinite-post",
errorCallback: function(){ $(".inf-more-but").css("display", "none") }
}, function() { // callback
alert("Manual click load finished");
});
$(window).unbind(".infscr");
$(".inf-more-but").click(function(e){
e.preventDefault();
var infinite_scroll = $(".infinite-content").infinitescroll("retrieve");
return false;
});

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.

how to make qooxdoo effects work?

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)

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');
}
});
});