Subversion Repositories eFlore/Archives.cel-v2

Compare Revisions

Ignore whitespace Rev 36 → Rev 31

/trunk/src/org/tela_botanica/client/modeles/ImageCarnet.java
10,26 → 10,18
*
* Classe representant une image du carnet,
* elle ne contient pas d'image à proprement parler mais
* plutôt les informations associées ainsi que l'url distante.
* C'est une table de hachage qui contient des paires propriété/valeur
* plutôt les informations associées ainsi que l'url distante
*
*/
public class ImageCarnet extends HashMap {
 
/**
* Constructeur avec un objet JSON
* @param image
*/
public ImageCarnet(JSONObject image)
{
// l'objet JSON est une table de hachage
Set im = image.keySet() ;
// on la parcourt pour chaque clé
for (Iterator iterator = im.iterator(); iterator.hasNext();) {
// si elle est associée à une valeur, on l'ajoute
String key = (String) iterator.next();
if(image.get(key).isString() != null)
{
38,7 → 30,6
}
else
{
// sinon on ajoute la clé avec une valeur vide
String valeur = " " ;
this.put(key, valeur) ;
}
47,9 → 38,6
 
}
/**
* Surcharge de toString qui affiche toutes les propriétés de l'image
*/
public String toString()
{
String valeur = " ";
68,13 → 56,6
return valeur ;
}
/**
* Pour éviter que l'on traite des valeurs nulles à l'affichage
* on passe par cette fonction qui retire les charactères nuls qui font planter
* l'affichage, il ne faut pas utiliser get directement
* @param cle
* @return la valeur associée à la clé
*/
public String renvoyerValeurCorrecte(String cle)
{
if(this.containsKey((cle)))
82,7 → 63,7
String valeur = (String)this.get(cle) ;
if(valeur.equals("null") || valeur == null)
{
return " " ;
return "null" ;
}
else
{
94,114 → 75,65
}
else
{
return " " ;
return "null" ;
}
}
 
/**
* Acesseur pour l'id de l'image
* @return l'id de l'image
*/
public String getId() {
return renvoyerValeurCorrecte("ci_id_image") ;
}
/**
* Acesseur pour le numero d'ordre de l'image
* @return l'ordre de l'image
*/
public String getOrdre() {
return renvoyerValeurCorrecte("ci_ordre") ;
}
/**
* Base de l'url serveur pour les images
* @return url racine pour les images
*/
public String getBaseUrl()
{
return "http://162.38.234.9/Documents/images_serveur/" ;
}
 
/**
* Renvoie le chemin et nom du fichier grand format
* @return le chemin du fichier grand format
*/
public String getUrl() {
return getBaseUrl()+(String)this.get("ci_id_image")+".jpg" ;
}
/**
* Renvoie le chemin et nom du fichier petit format
* @return le chemin du fichier petit format
*/
public String getSUrl() {
return getBaseUrl()+(String)this.get("ci_id_image")+"_S.jpg" ;
}
/**
* Renvoie le chemin et nom du fichier moyen format
* @return le chemin du fichier moyen format
*/
public String getMUrl() {
return getBaseUrl()+(String)this.get("ci_id_image")+"_M.jpg" ;
}
/**
* Renvoie la taille de l'image
* @return un tableau de deux string contenant la hauteur puis la largeur
*/
public String[] getTailleImage()
{
String[] XY = { renvoyerValeurCorrecte("ci_meta_height") , renvoyerValeurCorrecte("ci_meta_width") } ;
return XY ;
}
/**
* Renvoie la date exif associée à l'image
* @return la date associée à l'image
*/
 
 
public String getDate() {
return renvoyerValeurCorrecte("ci_meta_date_time") ;
}
 
/**
* Renvoie la ville associée à l'image
* @return la ville iptc
*/
 
public Object getIptcCity() {
return renvoyerValeurCorrecte("ci_meta_iptc_city") ;
}
 
/**
* Renvoie le fabricant de l'appareil
* @return le fabricant
*/
 
public String getMake() {
return renvoyerValeurCorrecte("ci_meta_make") ;
}
 
/**
* Renvoie le modele de l'appareil
* @return le modele
*/
 
public String getModel() {
return renvoyerValeurCorrecte("ci_meta_model") ;
}
/**
* Renvoie un tableau nom / valeur de toutes les metadonnées Iptc
* @return les métadonnées iptc
*/
public String[][] getMetadonnesIptc() {
String[][] metaIptc = new String[12][2] ;
235,11 → 167,7
return metaIptc ;
}
/**
* Renvoie un tableau nom / valeur de toutes les metadonnées Exif
* @return les métadonnées Exif
*/
public String[][] getMetadonnesExif() {
public Object[][] getMetadonnesExif() {
String[][] metaExif = new String[31][2] ;
int elem = 0 ;
273,11 → 201,7
}
/**
* Renvoie un tableau nom / valeur contenant les infos générales
* @return les infos générales
*/
public String[][] getInfoGenerales() {
public Object[][] getInfoGenerales() {
String[][] metaGen = new String[2][2] ;
290,20 → 214,11
return metaGen ;
}
/**
* Renvoie une string contenant les mots clés séparés par des ','
* @return les mots clés
*/
public String getMotsCles() {
return renvoyerValeurCorrecte("ci_meta_mots_cles") ;
}
/**
* Met à jour le commenentaire et la date
* @param commentaires le nouveau commentaire
* @param date la nouvelle date
*/
public void miseAJourInfoGenerales(String commentaires, String date)
{
put("ci_meta_comment",commentaires) ;
310,11 → 225,7
put("ci_meta_date",date) ;
}
/**
* Met à jour les mots clés
* @param motsClesEnCours la liste de mots clés séparés par des ','
*/
 
public void mettreAjourMotsCles(String motsClesEnCours) {
put("ci_meta_mots_cles",motsClesEnCours) ;
/trunk/src/org/tela_botanica/client/modeles/ImageAsynchroneDAO.java
8,23 → 8,20
import com.google.gwt.user.client.ResponseTextHandler;
import com.google.gwt.user.client.Window;
 
/**
* DAO d'accès à une image, n'est utilisé que pour l'écriture et pas pour la lecture des images
* qui se fait par paquet
* @author aurelien
*
*/
public class ImageAsynchroneDAO {
 
/**
* Met à jour la base de données avec toutes les données d'une image
* @param ic l'image à mettre à jour
*/
ImageMediateur iMediateur = null ;
public void setIMediateur(ImageMediateur im)
{
iMediateur = im ;
}
public void SynchroniserBaseDeDonnees(final ImageCarnet ic)
{
String postData = "" ;
// on construit le post avec toutes les valeur de l'image
for(Iterator imgIt = ic.keySet().iterator();imgIt.hasNext();)
{
34,11 → 31,10
 
}
 
// et on envoie une requête asynchrone
 
HTTPRequest.asyncPost("jrest/inventoryImage/0/", postData, new ResponseTextHandler() {
public void onCompletion(String responseText) {
//TODO: ajouter une vérification de la mise à jour
}
45,24 → 41,17
}) ;
}
/**
* Met à jour la base de données avec les mots clés associés à l'image
* @param ic l'image à mettre à jour
*/
public void SynchroniserMotsClesImageBaseDeDonnees(final ImageCarnet ic)
{
String postData = "" ;
// on récupère les mots clés de l'image et on fabrique le post
String motsCles = ic.getMotsCles() ;
String id = ic.getId() ;
postData += "&ci_id_image="+id+"&ci_meta_mots_cles="+motsCles ;
 
// on envoie une requête asynchrone
HTTPRequest.asyncPost("jrest/inventoryImage/0/", postData, new ResponseTextHandler() {
public void onCompletion(String responseText) {
//TODO: ajouter une vérification de la mise à jour
}
69,21 → 58,15
}) ;
}
/**
* Supprime une image de la base de données
* @param ic l'image à supprimer
*/
public void supprimerBaseDeDonnees(final ImageCarnet ic)
{
// le post contient l'action delete pour JREST (qui ne gère pas DELETE comme une requête à part entière)
String postData = "" ;
postData += "&action=DELETE" ;
// on envoie un post avec l'id de l'image à supprimer
HTTPRequest.asyncPost("jrest/inventoryImage/0/"+ic.getId(), postData, new ResponseTextHandler() {
public void onCompletion(String responseText) {
//TODO: ajouter une vérification de la mise à jour
Window.alert(responseText) ;
}
}) ;
/trunk/src/org/tela_botanica/client/modeles/ListeImageCarnet.java
4,38 → 4,23
import java.util.Vector;
 
/**
* table de hachage composée d'ImageCarnet, renvoyé par les objets de type DAO
* pour les images.
* La clé est l'identifiant de l'image dans la base de données, et la valeur un objet
* de type ImageCarnet.
* GWT ne supporte pas encore les type paramètres mais quand il le fera il faudra créer la HashMap
* avec <String,ImageCarnet>
* vecteur composé d'ImageCarnet, renvoyé par les objets de type DAO
* pour les images
* @author aurelien
*
*/
public class ListeImageCarnet extends HashMap {
/**
* Constructeur sans paramètres
*/
public ListeImageCarnet()
{
super();
}
/**
* Constructeur avec paramètre
* @param taille la taille de la table de hachage
*/
public ListeImageCarnet(int taille)
{
super(taille);
}
/**
* Constructeur avec paramètre
* @param ic un tableau d'ImageCarnet
*/
public ListeImageCarnet(ImageCarnet[] ic)
{
super() ;
/trunk/src/org/tela_botanica/client/modeles/ListeImageAsynchroneDAO.java
3,7 → 3,6
import java.util.Iterator;
 
import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.image.ImageModele;
import org.tela_botanica.client.interfaces.Rafraichissable;
 
import com.google.gwt.json.client.JSONArray;
29,31 → 28,18
*/
public class ListeImageAsynchroneDAO {
/**
* Le modèle associé au DAO
*/
ImageModele iModele = null ;
ImageMediateur iMediateur = null ;
/**
* Setteur pour le modèle
* @param im le modèle à associer
*/
public void setIModele(ImageModele im)
public void setIMediateur(ImageMediateur im)
{
iModele = im ;
iMediateur = im ;
}
/**
* Envoie une requete au serveur jrest pour obtenir une liste d'images correspondant à des critères demandés
* @param r le rafraichissable qui a demandé les données
* @param criteres un tableau contenant les critères de selections
*/
public void ObtenirListeImages(final Rafraichissable r, String[][] criteres)
{
String requete = "" ;
// on construit les paramètres du get
if(criteres != null)
{
for (int i = 0; i < criteres.length; i++) {
66,16 → 52,12
}
}
// on envoie le get asynchrone
HTTPRequest.asyncGet("jrest/InventoryImageList/0/"+requete, new ResponseTextHandler() {
// si tout se passe bien on reçoit une réponse JSON
public void onCompletion(String responseText) {
final ListeImageCarnet photoData ;
 
final JSONValue responseValue = JSONParser.parse(responseText);
// si c'est un tableau
if (responseValue.isArray() != null) {
final JSONArray reponse = responseValue.isArray();
83,7 → 65,7
final int taillemax = reponse.size();
photoData = new ListeImageCarnet(taillemax);
// on le parcourt
for (int j = 0; j < taillemax ; j++) {
JSONObject image = (JSONObject)reponse.get(j) ;
90,7 → 72,6
ImageCarnet im = new ImageCarnet(image) ;
// et on en extrait les données pour construire la liste d'image
photoData.put(im.getOrdre(),im) ;
}
97,35 → 78,25
}
else
{
// si c'est un objet alors il n'y a qu'une réponse
if(responseValue.isObject() != null)
{
photoData = new ListeImageCarnet(1);
ImageCarnet im = new ImageCarnet(responseValue.isObject()) ;
// on crée une liste de 1 élement auquel on ajoute ce qui a été reçu
photoData.put(im.getOrdre(),im) ;
}
else
{
// sinon on crée une liste vide
photoData = new ListeImageCarnet(0) ;
}
}
// dans tous les cas on transmet la liste crée au rafraichissable en lui demandant de répandre les données car il est
// le premier à les recevoir
r.rafraichir(photoData,true);
}
});
}
/**
* Met à jour les valeurs d'une liste d'image donnée dans la base de données
* @param li la liste d'image à synchroniser avec la base
*/
public void SynchroniserBaseDeDonnees(ListeImageCarnet li)
{
// on parcourt toute la liste d'image
for(Iterator listIt = li.keySet().iterator() ; listIt.hasNext() ;)
{
String postData = "" ;
132,10 → 103,8
ImageCarnet enCours = (ImageCarnet)li.get(listIt.next()) ;
// pour chaque image on extrait les informations
for(Iterator imgIt = enCours.keySet().iterator();imgIt.hasNext();)
{
// qu'on place dans le poste
String key = (String)imgIt.next() ;
String valeur = enCours.renvoyerValeurCorrecte(key) ;
valeur.replaceAll("'", "\'") ;
143,11 → 112,9
}
// on fait un post asynchrone et on les envoie à jrest
HTTPRequest.asyncPost("jrest/inventoryImage/0/", postData, new ResponseTextHandler() {
HTTPRequest.asyncPost("jrest/inventoryImage/0/", postData, new ResponseTextHandler() {
public void onCompletion(String responseText) {
//TODO: vérifier mieux le succès del a requête
}
155,31 → 122,23
}
}
/**
* Supprime des image sur le serveur par rapport à leur identifant
* @param ids un tableau d'identifiants d'images à supprimer
*/
public void supprimerBaseDeDonnees(String[] ids)
{
String postData = "" ;
// on fait un delete dans le post (jrest ne gère pas delete comme une action à part entière)
postData += "&action=DELETE" ;
String uid = "" ;
// on concatène les ids
for (int i = 0; i < ids.length; i++) {
uid += ids[i]+"," ;
}
// et on envoie ça au serveur
HTTPRequest.asyncPost("jrest/inventoryImageList/"+iModele.getIdentifiant()+"/"+uid, postData, new ResponseTextHandler() {
HTTPRequest.asyncPost("jrest/inventoryImageList/"+iMediateur.getIdentifiant()+"/"+uid, postData, new ResponseTextHandler() {
public void onCompletion(String responseText) {
// quand la requête est éxecutée on le signale au modèle poru qu'il mette à jour les données
// et en notifie le médiateur
iModele.requeteTerminee() ;
iMediateur.rafraichirToutesVues() ;
}
}) ;
/trunk/src/org/tela_botanica/client/modeles/NombreImageAsynchroneDAO.java
1,7 → 1,6
package org.tela_botanica.client.modeles;
 
import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.image.ImageModele;
import org.tela_botanica.client.interfaces.Rafraichissable;
 
import com.google.gwt.json.client.JSONArray;
12,35 → 11,16
import com.google.gwt.user.client.HTTPRequest;
import com.google.gwt.user.client.ResponseTextHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Image;
 
/**
* DAO qui renvoie le nombre d'image associées à différents critères donnés (utile pour la pagination)
* @author aurelien
*
*/
public class NombreImageAsynchroneDAO {
 
/**
* Le modèle associé au DAO
*/
private ImageModele iModele = null ;
private ImageMediateur iMediateur = null ;
/**
* Setteur pour le modèle
* @param im le modèlme à associer
*/
public void setIModele(ImageModele im)
public void setImediateur(ImageMediateur im)
{
iModele = im ;
iMediateur = im ;
}
/**
* Envoie une requete au serveur jrest pour obtenir le nombre d'images correspondant
* à des critères données en paramètres
* @param r le rafraichissable qui demande la mise à jour
* @param criteres un tableau nom/valeur des critères pour les images
*/
public void obtenirNombreImages(final Rafraichissable r, String[][] criteres)
{
String requete = "" ;
47,7 → 27,6
if(criteres != null)
{
// on construit les paramètres du get avec les critères (&critere1=valeur1&critere2=valeur2 etc...)
for (int i = 0; i < criteres.length; i++) {
if(!criteres[i][0].equals("ci_ordre"))
65,21 → 44,17
}
}
// on fait un get asynchrone
HTTPRequest.asyncGet("jrest/InventoryImageCount/"+iModele.getIdentifiant()+"/"+requete, new ResponseTextHandler() {
HTTPRequest.asyncGet("jrest/InventoryImageCount/0/"+requete, new ResponseTextHandler() {
public void onCompletion(String responseText) {
final JSONValue responseValue = JSONParser.parse(responseText);
// si la requete se passe bien on reçoit un tableau JSON
if(responseValue.isArray() != null)
{
// qui contient une valeur : le nombre d'images correspondant au critères
JSONValue res = responseValue.isArray().get(0) ;
JSONString reponseNombre = res.isString() ;
int maxImages = (int)Integer.parseInt(reponseNombre.stringValue()) ;
int[] nbImages = {maxImages} ;
// on le met dans un tableau d'entiers qu'on tranmset au demandeur de la mise à jour
r.rafraichir(nbImages, true) ;
}
/trunk/src/org/tela_botanica/client/modeles/MotsClesAsynchroneDAO.java
1,54 → 1,42
package org.tela_botanica.client.modeles;
 
import java.util.HashMap;
import java.util.Iterator;
 
import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.image.ImageModele;
import org.tela_botanica.client.interfaces.Rafraichissable;
 
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.HTTPRequest;
import com.google.gwt.user.client.ResponseTextHandler;
import com.google.gwt.user.client.Window;
import com.gwtext.client.data.Node;
import com.gwtext.client.data.Tree;
import com.gwtext.client.widgets.tree.TreeNode;
 
/**
* DAO d'accès à l'arbre de mots clés
* @author aurelien
*
*/
public class MotsClesAsynchroneDAO {
/**
* Le modele associé au DAO
*/
private ImageModele iModele = null ;
private ImageMediateur iMediateur = null ;
/**
* Setteur pour le modèle
* @param im le modèle à associer
*/
public void setIModele(ImageModele im)
public void setIMediateur(ImageMediateur im)
{
iModele = im ;
iMediateur = im ;
}
/**
* Envoie une requete au serveur jrest pour obtenir l'arbre des mots clés
* @param r le rafraichissable qui demande les données
*/
public void obtenirListeMotsCles(final Rafraichissable r)
{
// on demande tous les mots clés associés à l'utilisateur
HTTPRequest.asyncGet("jrest/InventoryKeyWordList/"+iModele.getIdentifiant(), new ResponseTextHandler() {
HTTPRequest.asyncGet("jrest/InventoryKeyWordList/"+iMediateur.getIdentifiant(), new ResponseTextHandler() {
 
public void onCompletion(String responseText) {
final JSONValue responseValue = JSONParser.parse(responseText);
// si la requête est un succès on reçoit un tableau
if (responseValue.isArray() != null) {
final JSONArray reponse = responseValue.isArray();
// et on met à jour le demandeur des données
 
r.rafraichir(reponse, true) ;
}
}
55,10 → 43,7
});
}
/**
* Envoie requete au serveur jrest pour ajouter un mot clé
* @param motcle le mots clés à ajouter avec son parent et son identifiant
*/
public void ajouterBaseDeDonnees(String motcle)
{
if(!motcle.equals(""))
65,12 → 50,11
{
String postData = motcle ;
// on fait un post asynchrone
HTTPRequest.asyncPost("jrest/InventoryKeyWordList/","&identifiant="+iModele.getIdentifiant()+postData, new ResponseTextHandler() {
HTTPRequest.asyncPost("jrest/InventoryKeyWordList/","&identifiant="+iMediateur.getIdentifiant()+postData, new ResponseTextHandler() {
public void onCompletion(String responseText) {
// si on reçoit une erreur d'ajout, on affiche un message d'erreur
if(responseText.equals("ERROR"))
{
Window.alert("Attention, la base de données des mots clés n'est plus synchronisée avec l'application," +
82,10 → 66,6
}
}
/**
* Envoie requete au serveur jrest pour supprimer un mot clé
* @param motcle le mots clés à supprimer
*/
public void supprimerBaseDeDonnees(String motcle)
{
if(!motcle.equals(""))
93,7 → 73,7
String postData = "" ;
postData += "&action=DELETE" ;
HTTPRequest.asyncPost("jrest/InventoryKeyWordList/"+iModele.getIdentifiant()+"/"+motcle,postData, new ResponseTextHandler() {
HTTPRequest.asyncPost("jrest/InventoryKeyWordList/"+iMediateur.getIdentifiant()+"/"+motcle,postData, new ResponseTextHandler() {
public void onCompletion(String responseText) {
108,10 → 88,6
}
}
 
/**
* Envoie requete au serveur jrest pour modifier un mot clé
* @param motcle le mots clés à modifier avec son parent et son identifiant
*/
public void modifierBaseDeDonnees(String motcle) {
if(!motcle.equals(""))
120,7 → 96,7
String postData = "" ;
postData += "&action=modification"+motcle ;
HTTPRequest.asyncPost("jrest/InventoryKeyWordList/"+iModele.getIdentifiant() ,postData, new ResponseTextHandler() {
HTTPRequest.asyncPost("jrest/InventoryKeyWordList/"+iMediateur.getIdentifiant() ,postData, new ResponseTextHandler() {
public void onCompletion(String responseText) {
132,10 → 108,6
}
/**
* Envoie requete au serveur jrest pour modifier un mot clé
* @param motcle le mots clés à ajouter avec son ancien parent, son nouveau et son identifiant
*/
public void deplacerBaseDeDonnees(String motcle) {
if(!motcle.equals(""))
144,7 → 116,7
String postData = "" ;
postData += "&action=deplacement"+motcle ;
HTTPRequest.asyncPost("jrest/InventoryKeyWordList/"+iModele.getIdentifiant() ,postData, new ResponseTextHandler() {
HTTPRequest.asyncPost("jrest/InventoryKeyWordList/"+iMediateur.getIdentifiant() ,postData, new ResponseTextHandler() {
public void onCompletion(String responseText) {
/trunk/src/org/tela_botanica/client/modeles/ImageUploaderAsynchroneDAO.java
1,7 → 1,6
package org.tela_botanica.client.modeles;
 
import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.image.ImageModele;
import org.tela_botanica.client.interfaces.iMediateur;
 
import com.google.gwt.core.client.JavaScriptObject;
26,30 → 25,19
*/
public class ImageUploaderAsynchroneDAO {
/**
* Modele associé au DAO
*/
private static ImageModele iModele ;
private static ImageMediateur iMediateur ;
/**
* Setteur pour le modele
* @param im le modèle à associer au DAO
*/
public void setIModele(ImageModele im)
public void setIMediateur(ImageMediateur im)
{
iModele = im ;
iMediateur = im ;
}
/**
* Crée un panel d'upload simple aux fonctions réduites mais utilisant uniquement javascript
* (pour les utilisateurs qui n'ont pas java)
*/
private static void appelerUploadSimple()
{
UploadDialog up = new UploadDialog("Upload simple de fichiers") ;
up.setUrl("jrest/InventoryImage");
UrlParam id = new UrlParam("identifiant",iModele.getIdentifiant()) ;
UrlParam id = new UrlParam("identifiant",iMediateur.getIdentifiant()) ;
UrlParam[] params = {id} ;
up.setBaseParams(params);
58,7 → 46,7
 
public void onClose(Panel panel) {
iModele.requeteTerminee() ;
iMediateur.rafraichirToutesVues() ;
}
});
67,10 → 55,6
}
/**
* Crée une fenêtre contenant une applet java pour uploader plusieurs fichiers à la fois avec quelques
* fonctions avancées (nécessite le plugin java pour le navigateur)
*/
private static void appelerUploadMultiple()
{
final Window nPan = new Window("Upload multiple");
104,7 → 88,7
final String htmlForm =
"<form method=\"post\" name=\"postid\">"
+"<input type=\"hidden\" name=\"identifiant\" value=\""+iModele.getIdentifiant()+"\">"
+"<input type=\"hidden\" name=\"identifiant\" value=\""+iMediateur.getIdentifiant()+"\">"
+"</form>" ;
 
nPan.setHtml(appelApplet+htmlForm);
114,7 → 98,7
 
public void onClose(Panel panel) {
iModele.requeteTerminee() ;
iMediateur.rafraichirToutesVues() ;
}
124,10 → 108,6
nPan.show();
}
/**
* Fonction javascript native qui détecte la présence du plugin java pour le navigateur
* et appelle la méthode d'upload adaptée (appelerUploadSimple ou appelerUploadMultiple)
*/
public static native void choisirMethodeUpload() /*-{
var agt=navigator.userAgent.toLowerCase();