ugrás a tartalomhoz

ExtJs cikkek =]

inf3rno · 2010. Dec. 6. (H), 01.05
Sziasztok!

Nemrég kezdtem el foglalkozni extJs-el, és úgy döntöttem, hogy saját keretrendszer írása helyett jobb lesz ezt megtanulni kezelni. Weblaboron sajnos nincs kint egy cikk sem ezzel a keretrendszerrel kapcsolatban. Ha lenne közületek valaki, aki régóta ismeri a keretrendszert, és hajlandó lenne cikket írni róla, vagy akár csak egy részéről annak nagyon örülnék, és szerintem még sokan mások is rajtam kívül. :-)

Valószínűleg majd én is írok róla később, ha már jobban beletanultam, hogy hogyan mennek extJs-ben a dolgok. Ami elsőre tetszik, hogy az adat és a megjelenítés elég élesen elválik egymástól. Sajnos a leírás nem a legjobb hozzá, ill. arra sem találtam még cikkeket, hogy melyik objektum pontosan mire való. Most konkrétan egy layout szerkesztőn dolgozok, ami drag&drop-pal megy. Úgy gondoltam, hogy egy speckó TreeNodeUI-val meg tudom oldani a dolgot, hamarosan kiderül, hogy igazam volt e, vagy bebukom a projektet.
Nehéz volt gyorsan indulni extJs-el (péntek óta nézegetem). Van egy speciális adatformátumom, de nem tudom, hogy melyik objektumokat kell kiterjeszteni ahhoz, hogy ebbe a formátumba lehessen menteni egy fát, vagy ilyen formátumból kiolvasni. Végül az lett, hogy kiterjesztés helyett írtam saját osztályokat, amik TreeNode-okból felépítik a fát. Ha esetleg tudtok valami átfogó leírást arról, hogy melyik objektum nagyjából mire való, meg arról is, hogy a TreeNodeUI-t hogy érdemes kiterjeszteni, akkor azt nagyon megköszönném.
 
1

Jól döntöttél...

gabesz666 · 2010. Dec. 7. (K), 02.20
Jól döntöttél, iszonyú jó keretrendszer, mindent meglehet vele oldani. Én már 2. éve használom a munkámban. Szívesen segítek is, emlékszem én is rengeteget szívtam az elején :) A speckó adatformátum olvasásához az Ext.tree.TreeLoader-t kéne talán kiegészíteni/újradefiniálni. Mentéshez találtam egy TreeSerializer-t egy ext fórumban.
2

Ahm, köszi, ez a serializer

inf3rno · 2010. Dec. 7. (K), 12.17
Ahm, köszi, ez a serializer jó lesz, a TreeLoader-t én is néztem, de nekem úgy jött le, hogy az async betöltésre való, szóval hogy ajax-al leszedi valahonnan a dolgokat, nekem meg egyelőre úgy kéne, hogy megvan a string magában az oldalban, és abból kéne betölteni. Az egyedi TreeNodeUI-t még nem látom át, ugye azzal kell egyedi kinézetet adni a fádnak? Az enyém annyira egyedi, hogy szinte egy what you see is what you get layout szerkesztő. Remélem nem túl komplikált egy ilyet összehozni :-)

Vannak furcsaságai extjs-nek, pl én TreeNode-on beállítottam, hogy expandable: false, és mégis összecsukható... Meg csináltam egy Window-ot, amit ha X-el zárok be, és újranyitok, akkor a következő megjelenítés helyett a fámat kezdi el módosítani az extjs. Nem tudom ez mennyire normális, mindenesetre én kiszedtem az X-et, és raktam bele ok/cancel gombokat hide-al. Úgy már nincs gond.

Most olvasom a Learning extjs-t, hátha segít.
5

Ötletek

gabesz666 · 2010. Dec. 7. (K), 13.18
Találtam egy fórumot, ami azt hiszem segít a nem ajax alapú betöltéshez. Nem próbáltam ki a kódot, de csináltam hasonlót régebben, és akkor működött.
A TreeNodeUI-val a fa node-jainak kinézetét tudod befolyásolni. A layout szerkesztő feladatot még nem értem teljesen, ki tudnád fejteni (mit tud, hogy néz ki)?

A window-os kódrészletet ha bemásolod tudok segíteni. Furcsaságok akkor szoktak előjönni, ha az oldalon ID ütközés van. Pl az jutott most eszembe, hogy a window closeAction property-je hide-ra van állítva close helyett és ilyenkor csak elrejti az ablakot, ami nem baj, ha nem adsz meg az ablaknak id-t vagy nem hozod létre újra az ablakot. Mert két ablak ugyanolyan id-vel nem túl optimális. :)

A Learning extjs nagyon jó alapnap, biztos segíteni fog.
6

Nem adtam nekik id-t, szóval

inf3rno · 2010. Dec. 7. (K), 13.40
Nem adtam nekik id-t, szóval id ütközés biztos, hogy nicsen. A kód még nincs olyan formában, hogy ide szívesen bemásolnám :D Elég kusza...

A layout szerkesztő, amit csinálnom kell. Nagyjából úgy képzeld el, hogy az oldaladat feldarabolod oszlopokra, aztán ezekbe lehet további oszlopokat vagy tartalmakat (menü,kereső,hírek etc...) tenni. Nekem meg annyi a feladatom, hogy erre a egy drag-drop-os szerkesztőt csináljak. Na most ha belegondolsz, akkor ez a layout egy szimpla dom tree, tehát egy tree-vel meg lehet oldani a szerkesztését. A ki meg bepakolható elemeket meg egy (egyoszlopos) grid-ben vagy egy másik fában lehet tárolni, aztán onnan berántani a layout fába. Kb így képzeltem el. Az alap fa ui nyilván nem úgy néz ki, mint ahogy egy weblap, szóval módosítani kell a kinézetén. Egyelőre csak annyit akarok változtatni rajta, hogy kicsi dobozok legyenek egymásban, és mindegyiknek legyen egy neve. Meg a fának mindig nyitott állapotban kell lennie.

Köszi a fórum linket, megnézem hamarosan.
9

Learning extjs

inf3rno · 2010. Dec. 23. (Cs), 18.43
A Learning extjs alapvetően jó könyv, az elmúlt 2 hétben sajnos nem volt időm programozni zhk, egyéb munkák miatt, ezért még csak a harmadánál tartok. A könyv jól tagolt, a példák egyszerűek, jól elmagyarázzák velük a dolgokat. Azért van pár negatívum is. Ami már most szemet szúrt, hogy a php példákban nincs sql escape, szóval a kezdőket SQL injection-ös kód írására tanítják. A másik dolog, hogy nem szeretem a rövid változóneveket, amiket a példákban használnak. Dumálnak néha arról, hogy milyen rossz az átláthatatlan kód, aztán meg a saját kódjukat teszik átláthatatlanná. Annyira persze azért nem vészes a dolog, mert rövidek a példák, de hosszabbaknál már nehezen lehetne átlátni. Egyelőre a Tree-ig még nem jutottam, de 1-2 napon belül meglesz az is, aztán összedobom ezt a layout szerkesztőt, meg akkor már beteszem ide, hátha rajtam kívül más is tanul belőle.

szerk:
Na elolvastam a könyvet, végülis hasznos volt, de nem eléggé: uiProvider-ről egy szó nem esett... Nézegettem 1-2 fórumot, aztán szépen lassan összeállt a kép. Ha az ember JSON-ból tölti be a fát, akkor a TreeLoader hozza létre a node-okat, és ő állítja be az uiProvider-t a createNode metódusában. A TreeLoader-nek több provider-t meg lehet adni amiket egy map-ben tárol. Azt, hogy melyik node milyen providert kap a JSON-ban kell megadni.

json:

[
	{id: 1, text: "Alpha", leaf: true},
	{id: 2, text: "Beta", leaf: false, children:
		[
			{id: 3, text: "Gamma", leaf: true, uiProvider: "custom"}
		]
	}
]
tree:

Ext.tree.CustomNodeUI=Ext.extend(Ext.tree.TreeNodeUI,
{
	renderElements : function(n, a, targetNode, bulkRender)
	{
		//...
	}
});


Ext.onReady(function ()
{
	new Ext.tree.TreePanel(
	{
		loader: new Ext.tree.TreeLoader(
		{
			dataUrl: "test.json",
			uiProviders:
			{
				custom: Ext.tree.CustomNodeUI
			}
		}),
		root: new Ext.tree.AsyncTreeNode(
		{
			text: "Root",
			uiProvider: Ext.tree.CustomNodeUI
		}),
		renderTo: "layout-holder"
	});
});
Hát megizzasztott a téma, nagyon nehezen találtam meg a megoldást... :S
10

fail :S

inf3rno · 2010. Dec. 29. (Sze), 01.00
Közben rájöttem, hogy a saját TreeNodeUI készítése erősen gányolás. A TreePanel-be annyira be van drótozva, hogy ikonok vannak, hogy nyitjuk meg zárjuk a fa ágait és a többi, hogy kb 20 metódust kell üresre átírnom a saját UI-ban, hogy úgy működjön, ahogy én szeretném. Inkább csinálok egy saját fa megjelenítőt az Ext.data.Tree-ből és az Ext.data.Node-ból kiindulva. Apróbb tervezési hiba, hogy nem gondoltak arra az extjs készítői, hogy fát másképp is meg lehet jeleníteni. Kellene még egy köztes osztály a TreeNode elé, ami egy általános felületet ad a megjelenítésre. Egyébként sokan küszködnek hasonló problémákkal, ahogy néztem. Nem örülök ennek, ez van :S

Kicsit szőrszálhasogatás, de ha már quicktips init meg sima init, meg ki tudja még hányféle init lehet, akkor én csinálnék egy init osztályt, aminek a példányába be lehet regisztrálni, hogy mit akarunk inicializálni, és ami automatikusan beteszi magát az onReady-be...

Találtam egy egész értelmes összefoglalót extjs-ről, valami ilyesmi kellett volna, amikor indítottam ezt a topicot: link.


szerk:
A TreeNode és TreeNodeUI rész ott van elhibázva, hogy nem elég laza a csatolás közöttük. A TreeNode direktbe hívja meg a TreeNodeUI metódusait, ezért bonyolult új ui-t írni hozzá. A jobb megoldás az lenne, ha a TreeNode-nak lennének a megjelenítésre vonatkozó eseményei, melyeknek a kezelésére az ui beregisztrálna eseménykezelőket a létrejöttekor, ill. kiszedné ezeket a kezelőket a törlésekor/leválasztásakor. Így további előny lenne, hogy ugyanazt a node-ot egyszerre több ui-val is meg lehetne jelenítetni.
Egy másik dolog, hogy a TreeNodeUI-ban sima HTML-ből készülnek a dolgok. Ez nem feltétlen gond, viszont én jobb szeretném a TreeNodeUI-t valamilyen Panel-ből kiterjeszteni, hogy egyszerűbben fejleszthető legyen. A TreeLoader-rel kapcsolatban is vannak dolgok, amik nem tetszenek, szóval végső soron az lesz, hogy mindent átírok.
11

Biztos TreePanel?

T.G · 2010. Dec. 29. (Sze), 14.46
Szia! Meg tudod mutatni, hogy a fát miként rajzoltad át? Érdekes amiket leírtál, de valahol mégiscsak azt érzem, hogy az amúgy sem gyors ExtJS-t megölnénk, ha a node elemek a panel-ből származnának. Az már nekem is többször gondot okoz, hogy a node-nál még egy template változó sincs, amit esetleg felülírhatnánk, de másik oldalról a fa egy annyira konkrét komponens, amelyet a felhasználók 90% ilyen formában szeretné használna. És a maradék 10%-nak is a jelentős része inkább a TreeGrid-et hiányolja)

Ennél komolyabb változás esetén szerintem már felmerülhet, hogy nekünk nem is biztos, hogy a TreePanel-re van szükségünk. Szerintem, ha pusztán panel elemeket drag&drop –pal szeretnénk egymásba helyezni, akkor a TreePanel ágyúval verébre.
12

Egyelőre így állok

inf3rno · 2011. Jan. 4. (K), 07.15
Közben elkészült a beta verió :-)
Lehet tesztelni, meg kiegészíteni... Drag-drop, meg hasonló nyalánkságok még nincsenek benne, csak a megjelenítés, meg append, insert, remove van beleépítve.

Ext.ns("Ext.ux.tree");

Ext.ux.tree.TreePanel=Ext.extend(Ext.Panel,
{
	constructor: function (attributes)
	{
		Ext.ux.tree.TreePanel.superclass.constructor.apply(this,arguments);
		
		this.setTree(new Ext.ux.tree.Tree());
		this.getTree().setUI(this);
		this.getTree().on("rootnodeset",function ()
		{
			this.getUI().onRootNodeSet(this.getRootNode());
		});
		
		if (this.rendered)
		{
			this.load(this.root);
		}
		else
		{
			this.on("render",function ()
			{
				this.load(this.root);
			});
		}
	},
	setTree: function (tree)
	{
		this.tree=tree;
	},
	getTree: function ()
	{
		return this.tree;
	},
	setLoader: function (loader)
	{
		this.loader=loader;
	},
	getLoader: function ()
	{
		return this.loader;
	},
	setSerializer: function (serializer)
	{
		this.serializer=serializer;
	},
	getSerializer: function ()
	{
		return this.serializer;
	},
	onRootNodeSet: function (rootNode)
	{
		this.add(rootNode.getUI());
		this.doLayout();
	},
	uiProvider: null,
	createNodeUI: function (node)
	{
		return new this.uiProvider();
	},
	load: function (config)
	{
		var rootNode=this.getTree().createNode(
			config
		||
			(
				this.getLoader()
			&&
				this.getLoader().load()
			)
		);
		if (rootNode)
		{
			this.getTree().setRootNode(rootNode);
		}
	},
	save: function ()
	{
		this.getSerializer().save(this.getTree().getRootNode());
	}
});


Ext.ux.tree.Tree=Ext.extend(Ext.data.Tree,
{
	constructor: function (root)
	{
		Ext.ux.tree.Tree.superclass.constructor.apply(this,arguments);
		this.addEvents("rootnodeset");
	},
	setRootNode: function (root)
	{
//hmm maybe we need destroy here the old root and its ui
		Ext.ux.tree.Tree.superclass.setRootNode.apply(this,arguments);
		this.fireEvent('rootnodeset');
	},
	setUI: function (ui)
	{
		this.ui=ui;
	},
	getUI: function ()
	{
		return this.ui;
	},
	createNode: function (config)
	{
		var children=config.children;
		delete(config.children);
		var node=new Ext.ux.tree.Node(config);
		node.ownerTree=this;
		var ui=this.getUI().createNodeUI(node);
		node.setUI(ui);
		ui.setNode(node);
		if (children)
		{
			Ext.each(children,function (childConfig)
			{
				node.appendChild(this.createNode(childConfig));
			},this);
		}
		return node;
	}
});

Ext.ux.tree.Node=Ext.extend(Ext.data.Node,
{
	setUI: function (ui)
	{
		this.ui=ui;
	},
	getUI: function ()
	{
		return this.ui;
	},
	destroy: function (silent)
	{
		this.getUI().destroy();
		Ext.ux.tree.Node.superclass.destroy.apply(this,arguments);
	}
});

Ext.ux.tree.NodeUI=
{
	setNode: function (node)
	{
		this.node=node;
		
		var ui=this;
		
		this.getNode().on("append",function (ownerTree,node,newChild,index)
		{
			ui.onNodeAppend(newChild,index);
		});
		this.getNode().on("insert",function (ownerTree,node,newChild,refNode)
		{
			ui.onNodeInsert(newChild,refNode);
		});
		/*this.getNode().on("move",function (ownerTree,node,oldParent,newParent,refIndex,refNode)
		{
			ui.onNodeMove(oldParent,newParent,refIndex,refNode);
		});*/
		this.getNode().on("remove",function (ownerTree,node,oldChild)
		{
			ui.onNodeRemove(oldChild);
		});
		
		this.onNodeSet(this.getNode());
	},
	getNode: function ()
	{
		return this.node;
	},
	onNodeSet: function ()
	{},
	onNodeAppend: function (newChild,index)
	{
		this.add(newChild.getUI());
		this.refresh();
	},
	onNodeInsert: function (newChild,refNode)
	{
		this.insert(this.items.indexOf(refNode.getUI()),newChild.getUI());
		this.refresh();
	},
	/*onNodeMove: function (oldParent,newParent,refIndex,refNode)
	{
		moving elements on the node
	},*/
	onNodeRemove: function (oldChild)
	{
		this.remove(oldChild.getUI(),false);
		var dom=oldChild.getUI().el.dom;
		(dom.parentNode || dom.parentElement).removeChild(dom);
		this.refresh();
	},
	refresh: function ()
	{
		if (this.rendered)
		{
			this.doLayout();
		}
	}
};

Ext.ux.tree.NodeComponent=Ext.extend(Ext.Component,Ext.ux.tree.NodeUI); //leaf
Ext.ux.tree.NodeBoxComponent=Ext.extend(Ext.BoxComponent,Ext.ux.tree.NodeUI); //leaf
Ext.ux.tree.NodeContainer=Ext.extend(Ext.Container,Ext.ux.tree.NodeUI); //branch
Ext.ux.tree.NodePanel=Ext.extend(Ext.Panel,Ext.ux.tree.NodeUI); //branch
Csináltam egy alap példát a használatára:

Ext.ux.tree.BasicNodePanel=Ext.extend(Ext.ux.tree.NodePanel,
{
	frame:true,
	header:true,
	onNodeSet: function (node)
	{
		var text=node.attributes.text;
		if (node.isLeaf())
		{
			this.html=text;
		}
		else
		{
			this.title=text;
		}
	}
});

Ext.onReady(function ()
{
	new Ext.ux.tree.TreePanel(
	{
		renderTo: Ext.getBody(),
		width: 800,
		frame: true,
		uiProvider: Ext.ux.tree.BasicNodePanel,
		root:
		{
			text: "root",
			children: 
			[
				{
					text: "container",
					children:
					[
						{text: "item 1", leaf: true},
						{text: "item 2", leaf: true},
					]
				},
				{
					text: "container",
					children:
					[
						{text: "item 1", leaf: true},
						{text: "item 2", leaf: true},
					]
				},
				{text: "item 1", leaf: true}
			]
		}
	});
});
Néhány lehetőség, amire képes némi továbbfejlesztéssel:
  • Tetszés szerint lehet módosítani a createNodeUI-t ahhoz, hogy minden ághoz egyedi megjelenítés tartozzon valamilyen attribútum alapján.
  • Az ui hozzáadásánál át lehet írni, hogy többet is hozzáadhasson egy node-hoz, így több megjelenítés is tartozhat egyszerre egy fához.
  • Lehet írni hozzá egyéni loadert a betöltéshez, nem nagy kunszt. A loadernek ugyanolyan objektumot kell visszaadni, mint fent a root.
  • Lehet írni hozzá egyéni serializert a mentéshez. A serializer egy Ext.data.Node-t kap, amiből elég egyszerű bármilyen szöveget csinálni.
  • A NodeUI kiegészítésével lehet pl olyat, hogy bizonyos elemeket a megjelenítéskor csoportokba rendezzen, vagy mondjuk drag&drop-ot is bele lehet vinni.
  • Persze azt is meg lehet oldani, hogy a NodeUI sima html-el bíbelődjön és ne panelezzen. Ha már kérdés volt... (Alapból panelra dolgoztam ki, mert nekem arra van szükségem.)

Ezek a kiterjesztések olyan dolgok, hogy csinálja meg mindenki magának, én adtam egy jó alapot extjs-ben a fák kezelésére, viszont nincs kedvem mások helyett dolgozni. :-)
A drag-drop-ot még ki fogom dolgozni hamarosan, mert kell egy projecthez. Azt még talán megosztom, nem tudom mennyire zűrös extjs-ben.
13

Néhány apróság.

T.G · 2011. Jan. 5. (Sze), 09.11
Belenéztem a kódba, de néhány dolgot nem értettem... :)

A Ext.ux.tree.TreePanel tartozik a Ext.ux.tree.Tree-hez, vagy fordítva? Számomra zavaró, hogy milyen könnyedén hívogatják egymás belső függvényeit, szerintem kellene egy kis ide-oda pakolás, hogy csak az egyik irányba történjen a hívás.

Megnéztem az Ext kódját, de a save eseményt alig látni, miért nem change? :)

TreePanel konstuktorában mi történne, ha a load render előtt futna le? miért kell az a vizsgálat, illetve előfordulhat-e, hogy render előtt fut le?

Nem akarnál egy jobb példát csinálni? Mert az eszköz valószínűleg sokkal erősebb, mint, amit a példakód mutat.

(zárójelben, Weblaborból forráskódot ki lehet úgy másolni, hogy a sorszámot ne másoljon... elég zavaró:)
14

Szia! A save még alakulni

inf3rno · 2011. Jan. 5. (Sze), 10.52
Szia!

A save még alakulni fog, nem néztem meg, hogy hogyan működik egy sima serializer, majd ahhoz igazítom.

Az Ext.tree-nél is úgy van, hogy a TreePanel-hez tartozik minden, itt annyi a különbség, hogy a TreePanel létrehozza az adatokat tároló Tree-t, szóval a kettő mindig együtt jár, ezért nincs értelme különrakosgatni a dolgokat, de azért kíváncsi vagyok szerinted mi van rossz helyen?

Huhh, a renderrel megfogtál :-) Ránézésre nem lenne hatása, ha render előtt tolnám a loadot, szóval az ellenőrzést nyugodtan ki lehet venni. (Talán a drag&drop hozzáadásánál szükséges, hogy renderelve legyenek az elemek, amikor dropTarget-et meg dragSource-ot adok a rendszerhez. Majd megnézem...)

Köszi a hozzászólásokat, tényleg hasznosak voltak. Izmosabb példát majd később tolok, mert most átalakítás alatt van a kód, meg próbálom beletákolni a csoportok kezelését meg a drag&drop-ot. Alapból gondoltam olyanra a csoportokkal kapcsolatban, hogy a node-kat automatikusan több szintes csoportokba teszi a megjelenítésnél valami alapján. Valszeg ilyen lesz majd a példa, de az még 1-2 hét, mert kevés az időm mostanában ilyesmire. A drag-drop meg elég nehéz dió, pl nem tudom, hogy hogy lehet elérni, hogy jelezze, ha két panel közé ejtek be valamit, valszeg az lesz, hogyha a title-ra ejti, akkor számít majd két panel közöttinek, ha meg a body-ra, akkor meg magába a panel-be rakom majd. Egyelőre nincs jobb ötletem...

A forráskódra rá kell ereszteni egy "\s+\d+\.\s+" => "" replace-t, aztán jó lesz. :-) Amúgy tényleg zavaró, elvileg valahogyan csatolni is lehet forráskódot, de még nem jöttem rá, hogy hogyan. Inkább kiteszem majd githubra valamikor.

(A move része, amit kikommenteztem nem fog kelleni, mert remove+append/insert-ből áll össze.)
17

Ide-oda pakolás

T.G · 2011. Jan. 5. (Sze), 20.05
Most inkább csak brainstormingolok, mert sok esetben az okokat nem ismerem, csupán van egy érzésem, hogy némi refaktorálásra szükség volna.

Nekem elsőre a 11. sorban lévő esemény elkapását jelentette problémát, elsőre szerintem arra gondolna az ember, hogy azért csinálsz ilyet, hogy a két osztályt különválaszd, legalábbis eseménykezelést sok esetben ezért csinálunk. De itt az eseményhez nem rendelsz scope-t, így az a függvény egy az egybe átmehetne a Tree-hez. (Magyarul: létrehozol egy fát, majd létrehozás után azt mondod egy másik osztályba, hogy bizonyos esetekben csináljon valamit. Na, de ezt miért a TreePanel –nek kell mondani, vagy legyen ez initConfig, de akkor se esemény után)

A másik, hogy az uiProvider kihez tartozik? Az eredeti példádban még a node-khoz, jelenleg a TreePanel-hez. Ez sem biztos, hogy jó, az uiProvider helye a node, ha ott nincs, akkor mehetünk megkeresni. :)

Végül a root létrehozása sem biztos, hogy a helyén van, a TreePanel load-ja megkéri a fát, hogy hozzon létre egy node-t, majd ha ez sikerült, akkor a fánál beállítjuk, hogy ez a node legyen a gyökér elem. Nem lenne egyszerűbb a config-ot átadni a fának? (például elsőre létrehozáskor)

Mindamellett én itt az ellenőrzést lecserélném. 1. hiba dobásával leállnék. nincs fa gyökérelem nélkül. 2. valami root elemet azért is csinálnék, még ha elsőre nem is sikerült. :)

Illetve a kódot véleményem szerint kicsit összébb kellene nyomni. (és most nem a formázásra gondolok), több esetben olyan feltétel vizsgálat van, aminek semmi haszna. doLayout meghívható rendered nélkül is. Ezek a lényegről elviszik a figyelmet.

Félre ne értsd, ha nem tetszene az ötlet, akkor nem foglalkoznék ezzel a kóddal ennyit! :-) Illetve még egyszer megjegyzem, hogy az itt leírtakat nem próbáltam ki, csupán ötletelés, gyakorlat lehet, hogy az ellenkezőjét igazolná. :)
18

Yepp, még van mit tákolni

inf3rno · 2011. Jan. 5. (Sze), 21.36
Yepp, még van mit tákolni rajta, a Tree-t külön akartam választani a TreePanel-től, csak félúton elakadtam :D
Az onrootnodeset is emiatt van, ha beállítom a rootnode-t, akkor a megjelenítésnél is hozzá kell illesztenem a TreePanel-hez.
A createNode-hoz létrehozok egy "nodecreate" eseményt majd, és a TreePanel ahhoz fog beregisztrálni, hogy létrehozza a node-hoz az UI-t, így a Tree a megjelenítéstől függetlenül is létezhet... A getUI meg setUI metódusokkal még lehet, hogy lesz valami, ami a különválasztást szolgálja majd, a lényeg, hogy a végére olyan lesz, hogy több panel tud majd felcsatlakozni ugyanarra a fára, és megjeleníteni vagy manipulálni az adatokat. Valszeg hasonlóan lesz, mint a grid és store esetében, külön kell majd létrehozni a fát, ami az adattárolást csinálja, és külön kell a Paneleket, szóval a fa létrehozása ki fog kerülni a TreePanel konstruktorából, ahogy a Loader és a Serializer is, mert ugye az adatot töltöd be meg szerializálod, nem a megjelenítést. :-) Tényleg van még mit áthelyezni rajta, de lassan kialakul. :-)


Az uiProvider az a defaultUIProvider és a megjelenítéshez tartozik. Ebben a verzióban még nincs benne, hogy uiProviders map-et hozunk létre a treePanel-en, és oda tesszük azonosítóval az osztályokat, majd a node-ban azonosítóval hivatkozunk rájuk. Persze még ennél is tovább lehet menni, leginkább olyan irányba, hogy csinálunk egy detectProvider metódust az TreePanel-en, ami megállapítja a node valamilyen adata alapján, hogy milyen provider tartozik hozzá. Ez persze lehet ugyanúgy az uiProvider attribútum, de akár az is, hogy "A" betűvel kezdődik a szöveg rajta, vagy hogy levél vagy ág e, vagy bármi más.

A refresh új nevet kapott: onChange. Még várható valami olyasmi is, hogy egy bizonyos node-hoz tarozó UI dinamikusan lecserélhető lesz, vagy akár az egész fához tartozó uiProviders map is lecserélhető lesz, és a fa újraépíti magát az új map alapján... Ez a része még olyan, hogy sokféleképp meg lehet oldani, aztán most gondolkodok rajta, hogy mi a célszerű...

Van még olyan dolog is, hogy a loader-nek onLoad eseménnyel kell értesítenie a Tree-t majd, hogy megjöttek az adatok, és lehet kirajzolni a root-ot, mert a mostani megoldás csak szinkron módra alkalmazható.

A doLayout-nál volt egy ciklus, ami végigment az összes szülő elemen, ez nekem kellett egy saját megjelenítéshez, aztán átírtam a saját megjelenítőt, és kiszedtem a ciklust, a rendered meg bent maradt véletlenül. Ártani végülis nem árt :-)

Majd még ebben a hónapban frissítem a cuccot, az a helyzet, hogy van két szigorlatom, aztán 2 hétig biztos nem lesz időm ilyen fejlesztésekkel foglalkozni, csak annyival, ami a projekthez kell, mert már le kellett volna adnom a kódot. Valamikor január vége fele kiteszem github-ra, meg írok ide is.


szerk:
Ezt még lehet nem válaszoltam meg eléggé:
De itt az eseményhez nem rendelsz scope-t, így az a függvény egy az egybe átmehetne a Tree-hez. (Magyarul: létrehozol egy fát, majd létrehozás után azt mondod egy másik osztályba, hogy bizonyos esetekben csináljon valamit. Na, de ezt miért a TreePanel –nek kell mondani, vagy legyen ez initConfig, de akkor se esemény után)


Azért eseményekkel oldom meg majd teljesen a Tree és a TreePanel közötti kommunikációt, mert akkor a TreePanel bármikor leválasztható lesz a Tree-ről, vagy visszailleszthető rá. Szóval a TreePanel-nél jó helyen van, az eseménykezelőhöz reggelés, annyi, hogy a setTree-be kéne áttenni majd, meg ha előzőleg már lett fa beállítva, akkor arról le kell választani a TreePanel-t. A TreePanel és a Tree kommunikációját teljesen átírom ilyen eseménykezelősre majd, a node.setUI,getUI helyett meg megpróbálom máshogy lekérdezni, hogy melyik UI tartozik egy node-hoz. Elvileg minden tree elem kap egy id-t, szóval valszeg {node.id => ui} map lesz, az ui-nál meg marad a setNode,getNode, mert az csak egy node-hoz tartozhat, egy node viszont több ui-hez is. Remélem így már érthető, ha nem, akkor kérdezz nyugodtan.
19

Közben átgondoltam ezt az

inf3rno · 2011. Jan. 6. (Cs), 08.42
Közben átgondoltam ezt az egész ui témát, és nem tartom jónak, hogy az ui vezérli azt, hogy hogyan ad magához dolgokat, hogyan vesz el. Mondjuk ha az ui sima html-ből áll össze, akkor is létre kell hozni minden egyes node-hoz egy-egy objektumot. Sokkal gyorsabb lenne Builder pattern-el. A TreePanel létrehoz Manipulator osztályokat, a root hozzáadásánál, vagy a node.append/insert-nél meg kiválasztja, hogy melyik node-hoz melyik manipulator tartozik. Utána az a manipulator beregisztrál a megfelelő eseményekhez. Mondjuk ha leaf-ről van szó, akkor nem csinál semmit, ha meg branchről, akkor beteszi az eseménykezelőket az append,insert,move részekre. Ha egy elemet más kinézettel akarunk megjeleníteni, akkor a manipulator leszedi a régi ui-ról a gyerekeket, beteszi az új ui-t, és visszateszi rá a gyerekeket. Ha teljesen máshogy akarjuk a gyerekek hozzáadását kezelni, mondjuk csoportokat hozunk létre, és a csoportok tagjait külön divekbe tesszük a szülő ui-ján belül, akkor a Manipulatort kell lecserélni egy másikra, viszont ez is megoldható így dinamikusan. Neki is állok, csak előbb még biokémiázok egy kicsit, muszáj tanulni a szigorlatra. :-)
15

Másolás

Poetro · 2011. Jan. 5. (Sze), 12.10
Nekem teljesen jól megy a kód kimásolása. De ha a te böngésződben nem megy, akkor próbáld meg kikapcsolt JavaScript-tel.
16

Kijelölés != Másolás

T.G · 2011. Jan. 5. (Sze), 19.24
A probléma az OL tag, nem a JS.

var textarea = $('<textarea>');
textarea.css({position: 'fixed', top: 0, left: 0, width: 600, height: 300});
$('body').append(textarea);
var code = '';
$('ol li').each(function () {
    var line = this.innerHTML
        .replace(/\<\/?span[ \=\"a-z]*\>/gi, '')
        .replace(/&nbsp;/g, ' ')
        .replace(/&lt;/g, '<').replace(/&gt;/g, '>');
    code += line + "\n";
});
textarea.val(code);
:)
20

Megnéztem az Ext kódját, de a

inf3rno · 2011. Jan. 7. (P), 08.41
Megnéztem az Ext kódját, de a save eseményt alig látni, miért nem change? :)

Közben megnéztem én is, az Ext.data.Store load illetve save metódusokkal tölti be, és menti az adatokat, a Loader és a Serializer is ugyanezeket a funkciókat fogja ellátni a tree-nél, szóval szerintem maradhat a save elnevezés.
3

Ha lesz időm/energiám

Pred · 2010. Dec. 7. (K), 12.29
Úgy 1,5 évig toltam elég komolyan az Ext-et, igaz nem a mostani legfrissebb verziót. Ha valóban van rá igény néhány gondolatot - ahogy időm engedi - összeszedek szívesen a rendszerről. Talán még egy kis előadás szösszenetet is bevállalok a Docler Akadémiában valamikor, ha van érdeklődés.
4

Biztosan van.

inf3rno · 2010. Dec. 7. (K), 12.39
Biztosan van.
7

Engem érdekelne

aeternum · 2010. Dec. 18. (Szo), 02.30
egy szösszenet!
:)))

De akár egy step by step is!
:)))

Köszi, ha megcsinálod!
:)

aet
8

extjs.blog.hu

Kevlar · 2010. Dec. 18. (Szo), 14.52
21

Yii

imehesz · 2011. Jan. 8. (Szo), 19.11
ha a Yii (PHP) keretrendszert hasznalja valaki, meg kiegeszitot is talal extJS-hez: http://ext4yii.com/
22

Közben elkészültem a fa

inf3rno · 2011. Feb. 2. (Sze), 10.35
Közben elkészültem a fa kezelőmmel.
Ext.ux.tree

Van egy egyszerű példa, többre sajnos most nem volt időm. Néhány dolog még nincs letesztelve benne, ha valaki hibát talál, vagy egyéb észrevétele van, akkor legyen szíves szóljon itt, vagy küldjön mailt.

szerk:
Közben javítottam benne egy kisebb hibát, meg betettem a példába az adathoz még egy megjelenítőt, csak, hogy érzékeltessem mire képes a rendszer.

szerk2:
Töröltem belőle a builder patternt, mert feleslegesen bonyolította csak. Raktam bele proxy,reader,writer osztályokat, hogy lehessen szervertől leszedni és szerverre feltölteni a fát. Az egész nagyjából hasonló felületű lett, mint az Ext.tree-ben megadottak azzal a különbséggel, hogy ott a node.ui-val lehetett elérni a dolgokat, itt meg az ui.node-al, és a tree/node eseménykezelői hívják meg az ui objektumok metódusait. Így elég lazán csatolt lett a cucc, annyira, hogy több view-t is be lehet állítani ugyanahhoz a modelhez. Az adatok betöltéséért és mentéséért a TreeStore a felelős, bármilyen adat formát lehet használni megfelelő reader és writer beiktatásával, alapból a JSONReader és JSONWriter van megírva. A lényeg, hogy a tree-nek olyan objektum kell, mint amit az Ext.tree-ben json-ban adunk meg. A proxy alapból úgy van beállítva, hogy a megadott url-ről gettel szedje az adatokat, és posttal küldje vissza őket mentésre. Persze egy kis átírással szinte bármit el lehet érni. Körülbelül ennyi, amit tud, most írok egy komolyabb projektet erre építve, drag-droppal, csoportosítással meg mindennel, ha készen lesz, akkor kiteszem azt is. Ez valszeg a héten még megtörténik.