EXT JS Application Design Advice - extjs4

in need of EXT JS application design advice. here is a diagram of what I have so far:
http://screencast.com/t/RCdve5dO2
I have a window, with a toolbar. On the tb there are 3 menus, a button and a store to track some info. the window itself is an image which changes upon button click based on the values of the menus. i have a menu handler for this.
this all works fine and well with one window.
the issue i'm having is I can create multiple instances of the window on a drop event (drag from tree on the left). when more than one window is open there is some sort of menu collision. the menus on one window break when select an item on the other window. like so:
http://screencast.com/t/bbJ8RjlQK1b1
it seem all instances of the window seem to be sharing the same handler, or perhaps each window shares the same menu instance? i will need to investigate.
my question:
so taking a step back, the requirement is that each of the duplicate windows (and there could be many) must operate independently. from a design perspective, whats the best way to accomplish this?

Let me guess, you are defining objects or arrays for the component class outside of the initComponent function.
Can you post your code please?
You should declare all non-primatives inside initComponent like this:
Ext.define('SomeComponent', {
extend:'SomeOtherComponent',
title:'a string is a primitive type. so is a number',
initComponent: function(){
Ext.applyIf(this, {
someNonPrimitiveProperty:{ text:'arrays and objects are non-primitive' }
});
this.callParent(arguments); //always call this
}
});

Related

Is it possible to use browser->drag() from dusk with Vuedraggable?

We are using VueDraggable (and Vue) in our front-end and we are testing our front-end with Dusk.
I am currently trying to use $browser->drag('selector', 'selector') from dusk to drag objects from one list to the other, but I don't see anything happening during the test (although it might be the action is not visible) nor is the right result shown, the object does not end up in the indicated list.
I was wondering if anybody made a working example already of using $browser->drag() combined with Vue.draggable? I am asking since I don't know if I am trying the impossible or not.
There is an open issue for this on Dusk's Github. I had to open a new issue that can be found here since the original was closed for comment. The link contains a more thorough explanation, but the short answer and solution are highlighted here:
Problem: Laravel's Dusk does not trigger Vue.draggable events. To simulate a drag-and-drop Dusk does a "mouse down", "move mouse to location", and "mouse up" sequence. In theory this is correct but does not trigger Vue' s events.
Solution: Dusk's method does trigger mouse down and mouse up events, so we can simply use those events to trigger the ones desired.
$("a[draggable='true']").on("mousedown", function(event) {
$(this).trigger("dragstart");
});
$("div[droppable='true']").on("mouseup", function(event) {
$(this).trigger("drop");
});
This JSFiddle is an example of how it would work (though you need to implement it on a Laravel project to truly test, of course!).

Dojo DND creating multiple items

I got a question to which I have no answer after a couple of hours of trying and googling :(
I've created three dojo.dnd.Source components. It is used to couple a user to a project so to the left I've got projects and to the right I've got my users and in the center I got a canvas. I set up the relevant creators and checkacceptance functions and all is well.
Onto the center canvas a user can drop a project which is shown as a div containing all related users as div elements. The other dndtype that can be dropped is the user type, in that case I want to empty the canvas and show all projects to which te dropped user is related. As soon as I drop a project or user on the canvas the creator function is called. The problem is that the creator function returns 1 element that should be dropped, if I drop a user I need to draw several elements onto the canvas so the creator method isn't fully covering this since it returns only one element.
To cope with the default behaviour I tried to manually add projects to the canvas and returning only one, I know it ain't pretty :S It's working but I'm confronted with strange behaviour, if I move a project on the canvas it is treated as a user in stead of a project.
Bottom line, is there a way that you guys know of to drop one item and create multiple. I was searching to trigger the drop event myself but to no avail.
Thanks!
The event you are looking for is Source's onDrop event. Check the API docs for some more events you could use: there is a onDropExternal and onDropInternal for use inside and between Stores.
require(["dojo/dnd/Source"], function(Source){
var source = new Source({
onDrop = function(source, nodes, copy) {
//called only on the current target, when drop is performed
this.inherited(arguments); //execute the default onDrop function
//now add the node(s) to the other stores here
//you might be able to just do something like:
source2.insertNodes(nodes);//but this is untested ;)
}
});
});

How to replace jquery's live for elements that don't exist when the page is loaded

I have seen numerous advice on stackexchange and all over the web suggesting that I not use jquery's live function. And at this point, it is deprecated, so I'd like to get rid of it. Also I am trying to keep my javascript in one place(unobtrusive)--so I'm not putting it at the bottom of the page. I am unclear though on how to rewrite the code to avoid live for elements that don't yet exist on the page.
Within the javascript file for my site I have something like this:
$(function() {
$('button.test').live('click', function(){
alert('test');
});
});
.on( doesn't work since the element doesn't exist yet.
The button is in a page I load in a colorbox pop-up modal window. I'm not sure exactly where that colorbox window sits in the DOM but I think it is near the top.
I could use delegate and attach this to the document--but isn't the whole point of not using live to avoid this?
What is the best way to get rid of live in this case?
You can use .on() - http://api.jquery.com/on/
$(document).on("click", "button.test", function() {
alert('test');
});
If you use live() you can use die().
You can also use on() and off().
They do about the same thing but its recomended to use on.
I ended up avoiding both live and an on attached at the document level. Here's how:
Wrap all of the jquery code specific to objects in a page which loads in the colorbox window in the function like so:
function cboxready(){
...
}
The code wrapped in this function can attach directly to the objects (instead of attaching at the document level) since it will only get run once the colorbox window is open.
Then just call this function using colorbox's callback when you attach the colorbox, like so:
$('a.cbox').colorbox({
onComplete:function(){ cboxready(); }
});

Dojo : show() and hide() .... HOW?

I have a container element in which I create on the fly/place() a form, then another one..etc.
My goal is to switch between them i.e. hide all and show only the active form.
It hides alright, but I can't show the active back.
I tried using:
.style.display(none<->block) and visibility(visibility<->hidden)
dojo.style(...)
resize() and startup() after the changes
Several other variants i found on Internet from old dojo's
Nothing works.
/I need it to work with display, so that it does not occupy space./
Can you tell me what is the correct way to show and hide with dojo()
Also looked at this one :
How do I dynamically show and hide an entire TabContainer using DOJO?
Does not work.
The pseudo code I use is something like this :
....
//find or create the FORM element
form = dijit.byId(...);
if(typeof form != 'object') {
form = dojo.create('form', ....);
dojo.place(form,'containerx','last');
}
//hide all
dojo.query('#containerx > *').forEach(function(item){
dojo.style(item, 'visibility','hidden');// and all other variants i mentioned
})
//show only the current form
dojo.style(form, 'visibility','visible');
//if the dojo form obj was already created, then skip it
if (this.form_obj) return;
....build the form and the elements....
this.form_obj.startup()
thanx
I just answered the question in that thread you referenced in your question a few minutes ago. Basically it involved getting jQuery involved. Works great for me. I have all the tabs created statically (as opposed to programatically) and I'm able to manipulate whether they are shown or hidden with the help on jQuery. All the code any everything is in my post here:
How do I dynamically show and hide an entire TabContainer using DOJO?
Sounds like you might be looking for StackContainer functionality.
Just set things up so that the StackContainer has the dijit.form.Forms as children and you can use the selectChild method to choose what form to display.

What's the difference between .select, .show, and .load in jquery-ui tabs?

I see that there are three events fired when a tab is selected and I see the order in which the events are fired but I'm rather confused about which event to use or how these are truly different. If all three are fired, couldn't I just put my code in any of the events?
I must be missing something here. Can someone clarify?
So after messing with this more I'm going to share what I ended up doing in the hopes that it might help someone else.
I had to generate dynamic tabs based on data returned in an Ajax call. It's basically data by date where the tabs are the date and they display whatever data falls within that date.
Generating the tabs from the returned data was easy but I couldn't figure out how to write out the associated data. Finally (and I should have started here), I looked that the generated dom and noticed that a dynamically created tab also creates a div. Maybe that's obvious to some (it wasn't to me) and if it was in the documentation I missed it. Anyway, this code will generate tabs from an array and then append html to the associated div when the tab is clicked. I don't need all the variables but I thought that might make it more readable. Put the function for show before adding the tabs or it wont work!
var _sessionDates = getSessionDates(sessionData.Sessions);
var $tabs = $("#sub-tabs");
$tabs.tabs({
show: function(event, ui) {
var selected = $tabs.tabs('option', 'selected');
var _sessionDates = getSessionDates(sessionData.Sessions);
var grid = buildGrid(_sessionDates[selected]);
$('#' + _sessionDates[selected]).html(grid);
}
});
$(_sessionDates).each(function(i, dayOfShow) {
var d = dateFormat(dayOfShow, "mediumDate");
$tabs.tabs('add', '#' + dayOfShow, d);
});
Finally, I have to "scroll" through my data shown in the tab and I was able to do that with these two lines. The first line gives me the id of the div element corresponding to the selected tab (which is really the important part) and the second line just calls my method and passes in the id of the div less the '#'. My date is also my id. There's a global variable that I've changed outside of this that makes it work. I know that's bad and I'll remove it when I refactor it.
var $el = $($('#sub-tabs a')[$('#sub-tabs').tabs('option', 'selected')]).attr('href');
$($el).html(buildGrid($el.replace('#', '')));
select is triggered when a tab is clicked on, but before the tab has been shown
load is triggered after the contents of a remote tab have been loaded (i.e. a tab whose content is not part of the initial page payload, but that is loaded via an ajax call when the user clicks on the related tab)
show is triggered after a tab has been shown
The jQuery documentation makes this relatively clear, but I had to experiment in order to fully understand the difference between select and show.
This has been made more clear since the original question was asked so now the following is true:
Effectively, the functionality for "show" is now provided by "activate" and "select" is done with "beforeActivate" while "load" is still the same.
activate: (previously show) Triggered after a tab has been activated (after animation completes)
beforeActivate: (previously select) Triggered immediately before a tab is activated.
load: Triggered after a remote tab has been loaded.
Also provided are:
beforeLoad: Triggered when a remote tab is about to be loaded, after the beforeActivate event.
create: Triggered when the tabs are created.