_nec - webfejlesztés, front-end programozás, javascript, css, xhtml, ajax, air

Adobe AIR #4 Drag’n'Drop és Filefeltöltés

Az alapok után, ismerve az ablakkezelést és az eseményeket nézzünk meg egy összetettebb kérdéskört.

AIR alkalmazásunknak lehetősége van más alkalmazásokból különböző adatok fogadására, a GUI-ban megszokott egyszerű drag’n'drop műveletekkel. Míg művelet végrehajtása a felhasználónak könnyű, a háttérben jópár komplexebb dologra kell figyelni. Habár böngészőkben is használható javascript alapokon, webes fejlesztőknek ez eléggé új terület lehet, így előbb nézzük meg a művelet sajátosságait a konkrét példa előtt.

Események

A drag’n'drop műveletnek minimum két résztvevője van, ahonnan indul a drag és ahol végetér, közben pedig azok az elemek is reagálhatnak, melyekkel érintkezésbe kerül a mozgatott adat. A művelet során lényegében csak eseményekre hagyatkozhatunk, ezekkel zajlik az adathordozás.

Eseményszinten nézve ezt az alábbiak alkotják:
a forrás az adatmozgatás eredete

a forrás a mozgatás célpontja illetve lehetséges célpontjai

Ezekre az eseményekre figyelve kezelhetjük a műveletet illetve vezethetjük a felhasználót, hogy hova mit mozgathat, ügyelve a felhasználóbarát kezelésre.

Az eseményen belül innentől a dataTransfer objektumra koncentrálunk, ez tartalmazza a művelet során érkező adatokat.

Adat típusok

A böngészők nagy általánosságban az alábbi típusokat kezelik le a művelet során:
text, html, url, file. Ez utóbbi böngészőgyártótól függően még lebontható képre, helyi file-ra, stb.

Fontos megjegyezni. hogy a típust mindíg az adatmozgatás eredete állítja be, az esemény hordozza magával, a fogadó ellenőrizheti. Pl ha a címsorunkból kijelöljük a linket és azt mozgatjuk, az AIR szöveget fog látni. De ha pl az RSS feed ikonját mozgatjuk, már URL-nek látja. Itt a böngésző a forrás, az állítja be a típust.

Az AIR mozgatható adattípusai a következőek:

Ezek a flash képességeire emlékeztethet egyeseket, ami nem csoda, hisz az AIR esetében javascriptből félig flashbe lóg a lábunk. Az adattípust a dataTransfer.types tömb tartalmazza egyszerre többet is hordozhat, hisz pl egy html kódrészlet alapjában véve szöveg, de tartalmazhat linkeket és amúgy html formázott szöveg, így lehet akár három típusa is. Hogy ezeket miként használjuk fel, majd az adatok kinyerésénél megézzük.

Most – miután látjuk mikor és mit mozgathat a felhasználó – jön az, hogy mit kezdhet illetve kezdjen az adattal.

effectAllowed, dropEffect

Az adat forrása a mozgatás kezdetekor meghatározhatja milyen lehetőségek vannak az adat elhelyezését illetően. Az adatokat fogadó alkalmazás pedig kikötheti, hogy ő mit akar végrehajtani ezek közül. Ez a két paraméter az eseményben az dataTransfer.effectAllowed és a fogadónál a dataTransfer.dropEffect. Értékei a következők lehetnek:

Az első négy művelet egyenként megfelel az adott rendszer szabvány kurzorainak, amit felvesz az egérkurzor a művelet során. Pl ha intézőből mozgatunk file-t, az ‘all’ értékkel jön, mi pedig jelezhetjük egy file feltöltésnél hogy ez csak ‘copy’ azaz másolás lesz a lehetséges műveletek közül, ekkor az egérkurzor jelzi ezt nekünk.

Drop

A művelet vége a drop esemény, ekkor kezdhetjük meg a feldolgozását az adatnak amit kaptunk. Az eseményből a dataTransfer.getData( string mimetype ) metódussal nyerhetjük ki azt az adatot, amire típus alapján szükségünk van. A mimetype paraméter a fent ismertetett típusok egyike.

Sajnos ez így még korántsem tökéletes, próbálkozásaim során reprodukálható volt az a jelenség, hogy képet böngészőből mozgatva próbáltam elfogadtatni vagy vizsgáltatni AIRben, nagyokat fagyott a futtatókörnyezet. Gyakorlatban inkább a filelistával és feltöltéssel mutatom be a fentieket.

Példa: filefeltöltés drag’n'drop -ra

A tanulmányozás során négy zónát raktam le htmlbe ahova huzogathatok adatokat:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
	<div class="target link">
		<h1>Linkeket ide</h1>
		Ez csak linkeket fogad.
	</div>
	<div class="target text">
		<h1>Szövegelj ide</h1>
		Ez csak szöveget fogad.
	</div>
	<div class="target file">
		<h1>Fileok jöhetnek</h1>
		Ez csak fileokat fogad.
	</div>
	<div class="target image">
		<h1>Képes vagyok</h1>
		Ez csak képeket fogad.
	</div>

Majd oldalbetöltéskor meghatároztam az események lekezelését. Itt jegyezném meg, hogy bár kényelmes használni, sajnos a jQuery .bind eseménykezélese egyelőre erre nem jó, mert a továbbított Event objektum nem tartalmazza a dataTransfer objektumot.

19
20
21
22
23
	$('div.target').each(function(i,s){
		s.addEventListener("dragenter", dragEnterOver)
		s.addEventListener("dragover", dragEnterOver)
		s.addEventListener("drop", dragDrop)
	});

Aztán jöhetnek az eseménykezelők. Az elsőben (dragEnterOver) válogatom le, melyik mezőbe melyik elemet engedem.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
    function dragEnterOver(event){
		event.preventDefault();
		if( $(event.target).hasClass('link') && event.dataTransfer.types.indexOf("text/uri-list") > -1 ){
			event.dataTransfer.dropEffect = "link";
		} else if( $(event.target).hasClass('text') && event.dataTransfer.types.indexOf("text/plain") > -1){
			event.dataTransfer.dropEffect = "copy";
		} else if( $(event.target).hasClass('file') && event.dataTransfer.types.indexOf("application/x-vnd.adobe.air.file-list") > -1 ){
			event.dataTransfer.dropEffect = "copy";
		} else if( $(event.target).hasClass('image') && event.dataTransfer.types.indexOf("image/x-vnd.adobe.air.bitmap") > -1 ){
			event.dataTransfer.dropEffect = "copy";
		} else {
			event.dataTransfer.dropEffect = "none";			
		}        
    }

Mivel a statikus HTML elemek alapból nem támogatják a drag’n'drop-ot, azzal kezdjük, hogy az megakadályozzuk az alapértelmezett reakciót. Majd a zónák osztálynevei és a hordozott adat alapján leválogatjuk, hogy fogadjuk-e, és ha igen, miként fogadjuk az adatot.

Végül a drop esemény lekezelése, kinyerjük az adatot. Ezt most röviden összekötjük egy filelista feltöltéssel HTTP-n keresztül, javascriptből, röviden mert meglepően egyszerű.

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
    function dragDrop(event){
 
		var list = event.dataTransfer.getData("application/x-vnd.adobe.air.file-list")
 
		if( typeof list != "undefined"){
			var request = new air.URLRequest("http://valami.tavoli.domain.hu/upload.php");
			for (var i in list ){
				list[i].upload(
					request,
					'filefile'
				);
				// örömünkben írjuk ki a fileok neveit
				air.Introspector.Console.log(list[i].name);
			}
		}
	}

A getData és a mime-type használatával kinyerjük a fileokat (40.), ez minden esetben egy file lista, melynet tagjai File objektumok. Ha megnézzük a doksiban, látható, hogy van egy upload metódusa, amit a FileReference objektumból örököl, ami már egy flash objektum. De a js, hála a script összemosásnak, látja ezt a metódust és ha meghívja őket egyenként (44.-51.) egy URLRequest társaságában, fel is tölti őket.

Mára ennyi fért bele, jó kísérletezést, bónusz, vagy házifeladat a copy-paste és a clipboard használatának utánajárni, hasonló ezekhez. Következő részben az AIR alkalmazás natív rendszerszintű menükezelését nézzük meg.

Eddig az Adobe AIR-ről:

cimkék:

Hozzászólások, trackbackek [trackback url]

  1. Kaszás Balázs 11:18 | 2008.07.07

    Köszi, ismét kiváló cikk!

  2. Gixx 14:46 | 2008.07.23

    Bár ezt már mutattam neked, ennek ellenére az egyik legfincsibb részt kihagytad a cikkből: PROGRESS BAR

    Az utolsó kódrészletet kiegészíteném:

    function dragDrop(event){
    
      var list = event.dataTransfer.getData("application/x-vnd.adobe.air.file-list")
    
      if( typeof list != "undefined"){
        var request = new air.URLRequest("http://valami.tavoli.domain.hu/upload.php");
        for (var i in list ){
          list[i].upload(request,'filefile');
          list[i].addEventListener("progress", progressHandler);
        }
      }
    }
    
    function progressHandler(event){
        var percent = Math.round((event.bytesLoaded / event.bytesTotal) * 100);
        document.getElementById("progressBar").style.width = String(percent * 2)+"px";
        document.getElementById("progressText").innerHTML = percent + "% [" + (Math.round(event.bytesLoaded/1024)) + "KB /" + (Math.round(event.bytesTotal/1024)) + "KB]";
    }
    

  3. Gabesz 19:20 | 2009.05.14

    Nekem most olyanra lenne szükségem, hogy XML mentése fájlba sajátgépen. Már szenvedek vele egy ideje, de nem sikerül. Néha security errort ír ki, máskor valami sorrend hibát, megint máskor azt, hogy nem fájl…
    Nem igazán értem, hogy mit rontok el, valószínűleg kevésbé értem az egész fájlnyitás-zárás dolgot, mint gondolom.
    Van erre valami példád? Hálás lennék érte :)

  4. _nec 15:51 | 2009.05.15

    itt van pelda ilyenre probald meg ez alapjan

Szólj hozzá







kategóriák


del.icio.us

  • No bookmarks avaliable.

epp olvasom

  • A Clash of Kings

    A Clash of Kings by George R.R. Martin

flickr

  • Tuomas Holopainen - the Imagineer
  • The Flock
  • Christmas Crow
  • Geek joy
  • Fast Food - extreme edition
  • Teide north side
  • Teide National Park
  • Genesis
  • Rado Cerix
  • werk - _nec
  • werk - Strati

back to index