javascript - ¿Qué formato(tipo MIME) debo usar para las operaciones de arrastrar y soltar en HTML5?
drag-and-drop dto (3)
Estoy empezando a experimentar con HTML5 Drag and Drop. Luego, en el controlador de eventos dragstart deberíamos ejecutar setData()
, que recibe dos parámetros: formato y datos .
function dragstart_handler(ev) {
ev.dataTransfer.setData(''text/plain'', ''foobar'');
}
Quiero arrastrar algún tipo de "objeto" de un contenedor a otro contenedor, dentro de mi aplicación web. Por "objeto", me refiero a algo que tiene múltiples atributos (color, texto, autor, fecha, ...).
¿Qué tipo de formato (o tipo MIME) debo usar?
-
text/plain
? -
text/x-myapp-myobjtype
? -
application/x-myapp-myobjtype
? -
application/x-myapp.myobjtype+json
? - ¿algo más?
- ¿más de uno?
¿Cómo debo codificar mi objeto (el parámetro de datos de setData()
)?
- Tecla separada por comas (o cualquier otro delimitador) = pares de valores?
- Serializar el objeto utilizando JSON?
- ¿Solo un ID, y en la zona de caída debo recuperar el objeto completo usando solo el ID?
- ¿Enviar solo una referencia al objeto, sin siquiera serializar nada? (no es posible, el argumento de los datos debe ser una cadena)
(Me doy cuenta de que "Cómo encontrar un objeto para arrastrar y soltar" podría ser otra pregunta aquí, pero está estrechamente relacionado con la elección del tipo MIME)
Algunas referencias:
La especificación HTML5 tiene algunos ejemplos de arrastrar y soltar (ver el borrador de trabajo actual o la última versión ). En tales ejemplos, se utiliza un tipo MIME personalizado, y también se sugiere el uso de tipos MIME específicos del sitio. Ver este fragmento de código:
<p>Drop your favorite fruits below:</p>
<ol dropzone="move s:text/x-example" ondrop="dropHandler(event)">
<-- don''t forget to change the "text/x-example" type to something
specific to your site -->
</ol>
<script>
var internalDNDType = ''text/x-example''; // set this to something specific to your site
[...]
Entonces, eso es genial, ¡esto significa que debemos usar un tipo MIME personalizado! (a menos que en realidad estemos arrastrando texto sin formato, o solo una URL, o algo que ya tenga un tipo conocido)
Pero, ¿cómo creamos ese tipo MIME personalizado?
No encontré documentación sobre esto, así que miré otros tipos de MIME. La lista de tipos de medios de texto no tenía nada especial, pero la lista de tipos de medios de aplicaciones era bastante interesante. Déjame tomar una muestra de esa lista:
application/atom+xml
application/xhtml+xml
application/xmpp+xml
application/vnd.google-earth.kml+xml
application/vnd.google-earth.kmz
application/vnd.iptc.g2.newsitem+xml
application/vnd.iptc.g2.packageitem+xml
application/vnd.nokia.iptv.config+xml
application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
application/vnd.yamaha.openscoreformat.osfpvg+xml
application/vnd.hal+json
application/vnd.hal+xml
Puedo notar un patrón para hacer nombres:
- Un punto separa jerárquicamente varios "elementos" (por ejemplo,
config
es hijo deiptv
, es decir, hijo denokia
, es decir, hijo devnd
). - Un guión separa las palabras compuestas (como en
google-earth
yopenxmlformats-officedocument
). - Un signo más sirve para especificar aún más el formato de serialización (
+json
y+xml
en estos ejemplos). - El prefijo
x-
debe usar para tipos MIME no registrados con IANA (y, por lo tanto, no se muestra en esa lista).
Según estas reglas, puedo sugerir el uso del siguiente tipo MIME:
application / x-mysite.myobject + json (o application / x-mysite.parentobject.childobject + json )
Esta parece ser la forma más precisa y correcta de especificar un tipo MIME personalizado para un objeto de aplicación web codificado en JSON.
Use ''application / json'' como envoltorio para cualquier otro metadato que le guste, incluido el tipo mime de archivos vinculados, o el html que desea usar en el navegador.
{ ''assets'': [
{
''color'': ''foo'',
''text'': ''bar'',
''uri'': ''http://'', // location of asset
''type'': ''application/zip'', // mime-type of asset
''html'': ''<div>html representation</div>''
// .. more properties
}
// ...more assets
]
}
Actualización: este error de Chrome se ha corregido desde la versión 19.
Si mi objetivo es ser compatible con Google Chrome (la versión 12 es la más reciente ahora), entonces debo limitarme a text/plain
.
Esto se debe a que Chrome ha implementado incorrectamente el objeto dataTransfer , y hay un error abierto acerca de que dataTransfer no funciona con texto o URL .
He escrito una simple desmontración en jsFiddle . Funciona correctamente en Mozilla Firefox 3.6 e incluso en el navegador Arora (versión 0.10.2, WebKit versión 533.3). Solo para estar completo, mi versión de Chrome es 12.0.742.112 (WebKit versión 534.30). El código de demostración también está disponible a continuación:
<div id="drag" draggable="true">Drag me!</div>
<div id="drop">Drop here!</div>
#drag, #drop {
padding: 1em 2em;
margin: 1em 0;
}
#drag {
background: #CFC;
}
#drop {
background: #FCC;
}
function dragstart_handler(ev) {
console.log(''dragstart'');
ev.dataTransfer.setData(''text/x-example'', ''Foobar'');
}
function dragover_handler(ev) {
// Accepting whatever is dragged over here
ev.preventDefault();
}
function drop_handler(ev) {
console.log(''drop'');
console.log(ev.dataTransfer.types);
if (ev.dataTransfer.types) {
var i;
for (i = 0; i < ev.dataTransfer.types.length; i++) {
var type = ev.dataTransfer.types[i];
console.log(type, ev.dataTransfer.getData(type));
}
}
console.log(ev.dataTransfer.getData(''text/x-example''));
}
var drag = document.getElementById(''drag'');
drag.addEventListener(''dragstart'', dragstart_handler, false);
var drop = document.getElementById(''drop'');
drop.addEventListener(''dragover'', dragover_handler, false);
drop.addEventListener(''drop'', drop_handler, false);