Mostrando entradas con la etiqueta Ajax. Mostrar todas las entradas
Mostrando entradas con la etiqueta Ajax. Mostrar todas las entradas

lunes 10 de marzo de 2008

Pop-ups con ThickBox

Pasos a seguir para implementar un pop-up Ajax no intrusivo con archivos JavaScript de bajo peso (unos 30k en total):

  • Incluir las librerías JavaScript de jQuery y ThickBox:
<script type="text/javascript" src="path-to-file/jquery.js"></script>
<script type="text/javascript" src="path-to-file/thickbox.js"></script>
  • Importar hoja de estilos:
<link rel="stylesheet" href="path-to-file/thickbox.css" type="text/css" media="screen" />
  • Construir enlace de la siguiente manera:
<a href="archivo?height=640&width=480&modal=true" title="Titulo" class="thickbox">Texto o imagen del enlace</a>

Ver demos y descargar liberías en jquery.com/demo/thickbox.

¿Conoces alguna forma mejor de hacer esto?

sábado 8 de marzo de 2008

Construcción visual de aplicaciones web Ajax-Java con WaveMaker

El entorno de desarrollo de WaveMaker es en sí mismo una aplicación web Ajax-Java. Puedes echarle un vistazo en estas demostraciones.



La herramienta es bastante fácil de usar y permite crear rápidamente aplicaciones web 2.0 con acceso a base de datos, servicios web, etc.

Se basa en dojo, Spring, Hibernate y Acegi. Utiliza Tomcat como servidor de aplicaciones. Permite cualquier base de datos soportada por Hibernate.

Ofrece funcionalidades para el diseño visual basado en componentes, genereación del modelo de entidades y servicos de acceso a datos a partir del propio esquema de datos, asistentes para crear servicios Java o servicios web, enlace a datos (data binding) en el propio diseño visual de la aplicación, seguridad basada en LDAP o en base de datos, prueba de la aplicación a la vez que desarrollas, generación del fichero de despliegue war, etc.

Además, es gratis.

Descárgatelo: viene listo para utilizar, con Tomcat, una base de datos HSQLDB, algunas aplicaciones de ejemplo y enlaces a tutoriales y ayuda.

El inconveniente que le veo es que no cuenta con gran cantidad de componentes visuales que sean ricos, usables y estéticos. Sería ideal verlo funcionar con Ext-JS.

lunes 11 de febrero de 2008

Liberado GWT-Ext 2.0

Estos no paran... se ha liberado GWT-Ext 2.0, un conjunto de widgets GWT basados en Ext JS. Increibles. No hay más que verlos en acción:

sábado 2 de febrero de 2008

Integración de GWT con Spring e Hibernate

En GWT-Widget han desarrollado GWT Server Library, una librería que permite la integración de GWT con Spring.

En una aplicación GWT, la arquitectura está configurada de la siguiente manera:

  • Capa de presentación, formada por los widgets GWT que se ejecutan en el navegador.
  • Lógica de negocio, compuesta por los servicios RPC que se ejecutan en el servidor web (servlets que mapean los métodos Java correspondientes).
  • Modelo de objetos, que son serializados por la RPC.
Con GWT Server Library la lógica de negocio se delega en Spring, con todas las ventajas de este framework basado en componentes, orientado a aspectos, que proporciona mecanismos de autenticación, logging, manejo de transacciones y acceso a base de datos, de forma limpia y no intrusiva, mateniendo el código desacoplado, mediante inyección de independencia, basada en la configuración sencilla de ficheros XML.

Para el manejo de objetos, hibernate4gt resuelve el "lazy loading remoto", etc.


(Vía George Georgovassilis, donde puede verse un ejemplo detallado de la integración, disponible para descargar).

miércoles 23 de enero de 2008

G4jsf: Componentes JSF con GWT

G4jsf es un subproyecto open source, bajo el proyecto Ajax4JSF, que ahora pertenece a JBoss, junto con RichFaces.

GWT facilita el desarrollo con Ajax, de forma que los desarrolladores no tengan que preocuparse del JavaScript subyacente. Esto se consigue mediante widgets, que son creados directamente desde Java.

Por otra parte, JSF ha tenido éxito por su enfoque basado en componentes, que separan el diseño de la presentación de la lógica subyacente, donde además es relativamente sencillo crear nuevos componentes que utilizar.

Pues bien:

La misión de G4jsf es que GWT y JSF no se perciban como tecnologías competidoras, sino que más bien se vean como tecnologías complementarias.


Este artículo muestra cómo se pueden utilizar componentes JSF definidos como widgets GWT.
<widget:component id="main" buttonlabel="#{bundle.buttonLabel}" greeting="Hello #{greetingBean.name}!">
<gwt:gwtlistener method="#{greetingBean.takeGreeting}" event="demo.gwt.client.EventData">
</gwt:gwtlistener>
Ver ejemplo de G4jsf en acción.

miércoles 16 de enero de 2008

Voces que importan, de Google

Ver los videos y las presentaciones de las conferencias de Google sobre GWT: "Voices That Matter: Google Web Toolkit Conference".

En esta conferencia de Bruce Johnson and Dan Peterson se habla sobre productividad (en inglés) [pdf]:



La misión de GWT es mejorar radicalmente la usabilidad, posibilitando a los desarrolladores la utilización de las herramientas Java existentes, para construir aplicaciones Ajax sin riesgos con cualquiera de los navegadores actuales.


Ver también otras listas de reproducción de GoogleDevelopers en YouTube.

domingo 13 de enero de 2008

Primeros pasos con GWT y eclipse

A continuación se muestra un resumen de los pasos a seguir para construir una aplicación Ajax con GWT y eclipse, según este artículo en IBM developerWorks:

En primer lugar descargar GWT y eclipse.

Crear un proyecto y una aplicación para importar en eclipse, con las utilidades projectCreator y applicationCreator de GWT:

C:\eclipse\workspace\miAplicacion>c:\gwt\projectCreator -eclipse miAplicacion

C:\eclipse\workspace\miAplicacion>c:\gwt\applicationCreator -eclipse miAplicacion com.elholgazan.ejemplos.client.MiAplicacion
Importar el proyecto en eclipse mediante "File>Import", seleccionando en primer lugar "General/Existing Projects into Workspace" y eligiendo después la carpeta del proyecto creada anteriormente: "C:\eclipse\workspace\miAplicacion". No marcar el check "Copy projects into workspace".

Con el archivo miAplicacion.launch se puede depurar y ejecutar la aplicación en modo "hosted". Es decir, simulando lo que será después, en modo web, la comunicación entre el cliente Ajax y el servidor.


Continuar con el artículo original (en inglés): 1ª parte, , y , donde se utiliza Apache Derby como base de datos relacional, se definen servicios asíncronos y finalmente se compila la aplicación (en JavaScript) para desplegarla y ejecutarla en modo web.

jueves 3 de enero de 2008

Varias formas de construir ventanas con Ajax


Ahí van algunos ejemplos:

16/01/20008:

¿Conoces otras formas?

martes 24 de julio de 2007

Recursos AJAX

Autocompletar: campos de texto con función de autocompletar.

1. AJAX AutoSuggest, de BrandSpankingNew

2. AJAX Autocompleter, de script.aculo.us

3. AJAX AutoCompleter, usando MooTools, de digi.tarald

4. Ajax autosuggest/autocomplete desde base de datos, de roScripts

5. Lista dinámica Ajax, de dhtmlgoodies

Edición instantánea: edición en línea de un documento html.

6. AJAX inline text edit 2.0, de yvoschaap

7. AJAX & CSS Flickr-like Editing Fields, de Dustin Bachrach

8. AJAX Instant Edit, de ideasfreelance

Menús y pestañas

9. 14 Tab-Based Interface Techniques

10. AJAX Menu Widget

11. AJAX Accordion Navigation

12. AJAX Dialogs, Menus, Grids, Trees and Views

13. AJAX Tab Module - Closeable Implementation

14. Ajax Tabs Content

15. AJAX Tabbed Content

16. MooTabs - Tiny tab class for MooTools

17. Dynamically loaded articles

Fecha, hora y calendarios

18. AJAX Datetime Toolbocks - Intuitive Date Input Selection

19. AJAX Calendars

Elementos interactivos

20. AJAX Floating Windows

21. AJAX Star Rating Bar

22. Ajax poller

Developer's Suite

23. AJAX HistoryManager, Pagination

24. AJAX Login System Demo

25. AJAX image preloader

26. AJAX Tooltips: Nice Titles revised | Blog | 1976design.com

27. 40+ Tooltips Scripts With AJAX, JavaScript & CSS | Smashing Magazine

28. AJAX Web Controls

29. AJAX syntaxhighlighter

30. GMail Ajax Style Username Signup

31. Gmail Ajax Style Check Username

32. Transparent Message

33. ModalBox — An easy way to create popups and wizards

34. AJAX File Uploads progress bar

35. Chained select boxes

36. Fly to basket

37. AJAX Key Events Signal

38. Disable form submit on enter keypress

Soluciones mejoradas

39. AJAX Instant Completion

40. Novemberborn: Event Cache

41. Altering CSS Class Attributes with JavaScript

42. Select Some Checkboxes JavaScript Function

43. AJAX Emprise Charts

44. amCharts: customizable flash Pie & Donut chart

45. PJ Hyett : The Lightbox Effect without Lightbox

Formularios

46. AJAX Upload Form

47. An AJAX contact form

48. AJAX contact form

49. Ajax.Form

50. Ajax form validation

51. Really easy field validation

52. AJAX fValidate

53. Ajax newsletter form

54. wForms

Grids y tablas

55. Data Grids with AJAX, DHTML and JavaScript | Smashing Magazine

56. Grid3 Example

57. AJAX Table Sort Script (revisited)

58. AJAX Sortable Tables

59. AJAX TableKit

Galerías

60. 30 Scripts For Galleries, Slideshows and Lightboxes | Smashing Magazine

61. AJAX LightBox, Sexy Box, Thick Box

62. AJAX Lightbox JS

63. AJAX Unobtrusive Popup - GreyBox

64. SmoothGallery: Mootools Mojo for Images | Full gallery

65. AJAX Libraries and Frameworks

Efectos visuales y animación

66. How to Create Digg Comment Style Sliding DIVs with Javascript and CSS

67. How to Create a Collapsible DIV with Javascript and CSS

68. How to Create an Animated, Sliding, Collapsible DIV with Javascript and CSS

69. AJAX Shopcart

70. Draggable content

71. Dragable RSS boxes

72. AJAX Pull Down Effect

73. AJAX Animation Effects

74. Combination Effects in scriptaculous wiki

75. AJAX Motion Transition

Utilidades básicas JavaScript

76. 9 Javascript(s) you better not miss !!

77. Top 10 custom JavaScript functions of all time

78. Hyperdisc Materials: JavaScript: Top 10: Automatic Breadcrumb Trail

79. JavaScript: Top 10 Most Useful JavaScripts

80. My Favorite Javascripts for Designers: Blakems.com ?

Recursos

81. MiniAjax.com

82. Ajax Rain

83. Max Kiesler - mHub : Ajax and rails examples & how-to’s

84. Ajax Resources

85. DZone Snippets: Store, sort and share source code, with tag goodness

domingo 22 de julio de 2007

Ejemplo de uso de DOM

Supongamos un documento con la siguiente estructura y con la función JavaScript especificada, que hace algunas modificaciones, lo que puede afectar también a la forma en que es visto por el usuario:

<html>
<head>

<title>Ejemplo de DOM</title>
<style type="text/css">
p.red {COLOR: red}
p.blue {COLOR: blue}
</style>
<script type="text/javascript">

function modificarEstructura() {
var paraArray = document.getElementsByTagName("p");
paraArray[0].firstChild.nodeValue = "Parrafo Uno";
paraArray[0].nextSibling.firstChild.nodeValue = "Parrafo Dos";
paraArray[0].nextSibling.nextSibling.firstChild.nodeValue = "Parrafo Tres";
var headline = document.getElementsByTagName("h1");
headline[0].removeChild(headline[0].firstChild);
var underline = document.createElement("u");
underline.appendChild(document.createTextNode("Nueva cabecera!"));
headline[0].appendChild(underline);

var thirdPara = document.getElementById("tercero");
thirdPara.setAttribute("class", "blue");

paraArray[0].style.fontWeight = "bold";
}
</script>

</head>
<body>
<h1>Cabecera!</h1>
<p class="red">Primero</p>

<p>Segundo</p>
<p id="tercero">Tercero</p>
<a href="JavaScript:modificarEstructura();">modificar estructura</a>

</body>
</html>

Puede verse como aquí se modifica el texto de los tres párrafos, se elimina el texto de la cabecera, se añade como cabecera un nuevo texto subrayado y se establece una clase de estilo CSS para el tercer párrafo. Finalmente se modifica directamente el estilo del primer párrafo, poniéndolo en negrita.

Hay que hacer notar que el cambio de valor de algunos atributos, como 'class', no está bien soportado en algunos navegadores. Así pues esto debería evitarse.

Para probarlo todo cree un archivo html y copie y pegue el código anterior. Después abra la página y haca lick en el enlace 'modificar estructura'.

Características de un objeto DOM

Estas son las propiedades y los métodos principales de un objeto DOM (Document Object Model):

Métodos del objeto document

  • getElementById(id)

Devuelve una referencia al elemento con un identificador dado.

  • getElementsByTagName(tag)

Devuelve un array con los objetos de una etiqueda determinada.

  • createElement(tag)

Crea un nuevo elemento con la etiqueta especificada.

  • createTextNode(text)

Crea un nuevo elemento de texto con el texto especificado.

Métodos del objeto element

  • getAttribute(attr)

Devuelve el valor de un atributo determinado.

  • setAttribute(attr, value)

Establece el atributo especificado a un valor concreto.

  • hasChildNodes()

Devuelve true si el elemento tiene elementos hijos. Si no devuelve false.

  • removeChild(child)

Elimina el elemento hijo especificado.

  • appendChild(child)

Añade un hijo al elemento.

Propiedades del objeto element

  • nodeValue, data

Cadena de texto contenida en un nodo de texto.

  • tagName

Nombre de la etiqueta de un elemento dado (por ejemplo "p", "div", "table").

  • parentNode

Padre del elemento actual.

  • nextSibling, prevSibling

Elementos siguiente y anterior, dentro del mismo nivel del elemento actual.

  • firstChild, lastChild

Primer y último elemento contenidos en el elemento actual.


Ejemplos de uso de XMLHttpRequest

Un ejemplo de petición GET síncrona y respuesta como texto:

var http = getHTTPObject();

if (http)
{
var url = 'http://www.web.com/ejemplo1.jsp';
var parameters = '?sabor=chocolate';
http.open('GET', url + parameters, false);
http.send(null);
if(http.status == 200)
alert(http.responseText);
}

Ejemplo de petición POST asíncrona con respuesta XML:
var http = getHTTPObject();

if (http)
{
var url = 'http://www.web.com/ejemplo2.jsp';
var parameters = 'sabor=cafe&pet=XML';
http.open("POST", url, true);
http.onreadystatechange = handleHttpResponse;
http.send(parameters);
}

function handleHttpResponse()
{
if (http.readyState == 4)
{
alert(http.responseXML.firstChild.value);
}
}

Características del objeto XMLHttpRequest

Estas son las propiedades y los métodos principales del objeto XMLHttpRequest.

Propiedades

  • onreadystatechange

Es una referencia a una función JavaScript. Se usa para especificar la función que debería ser llamada cuando cambie la propiedad readyState. El usuario debe establecerla antes de llamar al método open().

  • readyState

Valor entero de sólo lectura que representa el estado actual del objeto de petición:

0 - UNITIALIZED (no inicializado)
1 - LOADING (cargando)
2 - LOADED (cargado)
3 - INTERACTIVE (interactivo)
4 - COMPLETE (completo)

El objeto estará no inicializado hasta que se llame al método open(). El documento se carga cuando se retorna de la función send(). Después estará interactivo y responseText contendrá una representación parcial del documento que se recibe del servidor. Cuando el documento se reciba completamente será interpretado y estará disponible en la propiedad responseXML. En este momento readyState será igual a 4, completo.

  • responseText

Cadena de texto de sólo lectura con el cuerpo del documento de respuesta, una vez que readyState es 4. Si se intenta acceder antes puede dar error en Internet Explorer.

  • responseXML

Documento de respuesta interpretado como un objeto DOM, de sólo lectura.

  • status

Código de estado de la respuesta HTTP, de sólo lectura. Se supone que se puede acceder cuando readyState es 3, pero puede dar error en Internet Explorer si se accede antes de que sea 4.

  • statusText

Cadena de texto del estado de la respuesta HTTP, de sólo lectura. Lo dicho para status vale aquí.

Métodos

  • abort()

Si la petición ya ha sido enviada este método la cancela, de forma que readyState vuelve a ser 0.

  • getAllResponseHeaders()

Devuelve una cadena de texto que representa a todas las cabeceras de la respuesta.

  • getResponseHeader(header)

Devuelve una cabecera en particular, que se le debe indicar como parámetro (por ejemplo "Content-Type").

  • open(method, url, [async, [username, [password]]])

Inicializa el objeto de petición con la información que se le pasa como argumento:

El método de petición: "PUT" o "GET".
La URL (que puede tener parámetros si el método es "GET", para enviar parámetros al servidor).
De forma opcional un indicador de si la petición es síncrona (que bloquea la ejecución JavaScript) o asíncrona (no bloqueante). Por defecto es asíncrona.
Opcionalmente también, un nombre de usuario y contraseña.
  • send(body)

Envía la petición al servidor. Para peticiones "POST" el argumento pasado representa los parámetros pasados al servidor para obtener la respuesta. Este argumento no es opcional, conque debe establecerse a null si no se va a enviar nada como parámetro. Si la petición es síncrona, este método no volverá hasta que se reciba la respuesta. Si es asíncrona, se volverá inmediatamente.

  • setRequestHeader(header, value)

Establece un valor a una determinada cabecera de la petición (por ejemplo: "Content-Type" como "text/xml"). Debe llamársele después de open().

Uso típico

La forma típica de hacer las peticiones es:

  • Llamar primero al método open().
  • Opcionalmente establecer las cabeceras mediante llamadas a setRequestHeader().
  • Asignar una funcióna a onreadystatechange para gestionar la llamada asíncrona.
  • Enviar la petición con send().
  • Después se podrán leer las cabeceras de la respuesta con getAllResponseHeaders() y getResponseHeader().
  • Y finalmente, el objeto responseXML estará disponible para ser procesado.

Crear un objeto XMLHttpRequest con independencia del navegador

Este método puede usarse de la siguiente manera:

var http = getHTTPObject();
Y este es el código de la función:

function getHTTPObject()
{
var xmlhttp = false;

/*@cc_on
@if (@_jscript_version >= 5)
try
{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E)
{
xmlhttp = false;
}
}
@else
{
xmlhttp = false;
}
@end @*/

if (!xmlhttp && typeof XMLHttpRequest != 'undefined')
{
try
{
xmlhttp = new XMLHttpRequest();
}
catch (e)
{
xmlhttp = false;
}
}

return xmlhttp;
}

Ajax: Asynchronous Javascript and XML

Ajax (Asynchronous JavaScript and XML) es una tecnología que surge para crear aplicaciones web que mejoren la usabilidad y la experiencia del usuario.

Es simplemente un paso más en la evolución constante de la web, después de que llegaran tecnologías como HTML, CGI, lenguajes de script en servidor, JavaScript en cliente, hojas de estilo CSS, etc.

Ajax proporciona una nueva forma de representar las paginas en cliente de forma que:

  • A partir de la interacción con el usuario y mediante JavaScript, cuando se requiera mas información del servidor, se efectuaran pequeñas peticiones HTTP, síncronas o asíncronas.
  • El servidor responde con los datos requeridos en forma de documento XML y, usando JavaScript otra vez, se le representa al usuario en la forma correspondiente.

De esta manera, AJAX permite presentar nuevos contenidos interactuando con el servidor, sin que sea necesario recargar la pagina completa, sino solo la información adicional.

Este método reemplaza a la antigua técnica que consistía en usar IFRAMES invisibles para conseguir efectos similares.

Hay que tener en cuenta que, no solo los navegadores antiguos, sino también los más actuales que tengan JavaScript o ActiveX desactivados, no podrán hacer uso de la tecnología AJAX. Entonces, puede que haya que implementar también una interfaz de usuario sencilla para estos casos.

Algunas webs de ejemplo que usan AJAX son Flickr, GMail, Google Maps, etc.

XMLHttpRequest

La aplicación web, en cliente con JavaScript, utiliza el objeto XMLHttpRequest para la comunicación con el servidor. Este componente está presente en la mayoría de los navegadores modernos, ya sea de forma nativa o como componente ActiveX. La forma de crearlo, por tanto, dependerá del navegador.

Con este código, puede crearse un objeto XMLHttpRequest con independencia del navegador.

El uso de este objeto también puede ser diferente en cada navegador, pero tienen ciertas características comunes.

A continuación pueden verse algunos ejemplos de peticiones síncronas y asíncronas.

DOM y XML

DOM (JavaScript Document Object Model) es una API orientada a objetos para acceder o alterar, desde JavaScript, un documento HTML o XML, incluso el que se está representando en pantalla al usuario.

Existen varias recomendaciones del W3C, aunque basta que el navegador soporte la de nivel 1 para que puedan utilizarse la mayoría de los métodos necesarios.

Este nivel define el documento como un árbol de elementos que tienen diferentes atributos y valores.

Estos son los métodos principales, que se asume que son comunes a todos los navegadores modernos.

A continuación se muestra un ejemplo de JavaScript para alterar la estructura de árbol, donde se puede cambiar también el documento que se presenta al usuario.

Estilos CSS y DHTML

DHTML (HTML Dinámico) es un conjunto de técnicas para, entre otras cosas, modificar los estilos asociados a los diferentes elementos HTML usando JavaScript.

Sin embargo, también existen ciertas diferencias entre las opciones soportadas por los distintos navegadores.

Se puede cambiar la clase de un determinado elemento, o directamente su estilo.

Librerías JavaScript

Algunas librerías existentes para facilitar el trabajo de programar AJAX:

Librería de bajo nivel, que resuelve muchos de los problemas de compatibilidad entre navegadores y que da soporte a otras librerías de efectos.

Librería especializada en separar la presentación de la estructura. El código JavaScript se separa del propio HTML, de una forma fácil de entender, de forma similar a como se hace con las hojas de estilo CSS.

Esta basada en Prototype. Es una librería de efectos visuales muy potente, que da soporte a efectos como drag and drop, etc.

Servidor

Una forma de dar servicio a las peticiones AJAX es mediante servlets Java, que devuelvan el resultado XML correspondiente, con garantía de ser valido y estar bien formado.

Una opción más conveniente es usar JSP, que será más fácil de desarrollar y mantener, ya que no se mezcla el XML a devolver con la propia programación, sobre todo si se utilizan librerías de etiquetas. Sin embargo, el programa no garantiza que el resultado XML sea valido y este bien formado.

Otra posibilidad es utilizar servlets Java y XSLT. Los servlets tomaran ficheros XML en bruto, que después transforman mediante hojas XSL. Si para dar este servicio no se requiere información adicional a estos ficheros, bastara con un único servlet. El resultado será valido y estará bien formado. Es un método muy flexible y no se requiere parar el servicio para modificar estos ficheros XML y XSL. Pero el desarrollo exigirá mayores conocimientos y la aplicación será sensiblemente más lenta.

Una opción mas es con servlets y DOM, de forma que con esta API se interpreten y se generen los documentos XML. Con esto es más probable que el resultado este bien formado. Además, para el desarrollador puede ser conveniente manejar la misma API en cliente y en servidor, aunque la programación será más tediosa.

Marcos de trabajo en servidor

Para facilitar el desarrollo en servidor pueden utilizarse los siguientes marcos de trabajo:

Los documentos creados se descomponen en zonas, que pasan a tratarse independientemente: formularios que se envían, paneles que se actualizan, etc.

Librería de etiquetas JSP que permite crear componentes AJAX en cliente sin requerir conocimientos avanzados de JavaScript.

Crea el efecto de que el código que se ejecuta en servidor sea como si se estuviera ejecutando en cliente.

Librería que proporciona un API que permite abstraerse del conocimiento de JavaScript e incluso de HTML, para concentrarse en el diseño de la interfaz (la pagina web).

Ejemplos de uso

Estos son algunos casos típicos en los que puede utilizarse AJAX:

  • Validación en servidor de los campos de un formulario.
  • Autocompletar los campos de un formulario a partir de los campos ya cumplimentados y de la información en el servidor.
  • Recarga parcial de la página en función de las acciones del usuario.
  • Ejecutar ciertas acciones en el servidor, en función del comportamiento del usuario: mediante drag and drop, etc.