PDA

View Full Version : Probleme ctrl + click



alex1er
22 Feb 2007, 4:06 AM
Hi.

I think there is a bug in yui-ext?

I have many div i can select by click. I can have multiselection by pressing CTRL key and clicking on the div.

The problem i kave, it is that when i click on a div with the ctrl key down, a td which is in my div, change of style and has a blue border but i never set it this style.

Is there is a bug i the yui-ext?

Thanks

jack.slocum
22 Feb 2007, 6:28 AM
I don't know you are going to have to put up a page. I can tell you Ext is not listening for your control click unless you told it to. :)

alex1er
22 Feb 2007, 7:05 AM
Ok

So there is my code.


To produce the bug, click on an element list then press CTRL down and click one the same item.

You'll see that the item has a style that i never set.

Then if you click on the div of the list, this style will be removed.

So i don't know why.


Thanks

list.js



/**
* @constructor
* Creation d'une nouvelle Liste.
* @param {Object} config configuration options
*/
List =
function ( config )
{
this.init ( config );
};


/**
* _div
* x
* y
* width
* height
*
*/
List.prototype =
{
/**
* Identifiant du div container.
* @type String
*/
_id : null,

/**
* Objet Element de la yui-ext
* @type YAHOO.ext.Element
*/
_element : null,


/**
* Collection des Elements (html) de la liste.
* @type YAHOO.ext.util.MixedCollection
*
*/
_mapElement : null,


/**
* Collection des elements ajoutes a la liste.
* @type YAHOO.ext.util.MixedCollection
*/
_mapObject : null,


/**
* Collection des elements ajoutes a la liste.
* @type YAHOO.ext.util.MixedCollection
*/
_mapEvent : null,


/**
* Collection des elements selectionne dans la liste.
* @type YAHOO.ext.util.MixedCollection
*/
_mapSelected : null,


/**
* Index courant séléctionné.
* @type int
*/
_selectedIndex : null,

/**
* Les items sont-ils séléctionnables.
* @type boolean
*/
_selectable : false,


_multiselectable : false,

/**
* Fonction appellée lors du click sur un item de la liste.
* @type handler
*/
_onclick : null,

/**
* Doit on mettre en surbrillance l'item lors de son survol par le pointeur de la souris
* @type boolean
*/
_highlightOnmouseover : false,
/**
* Tableau de fonctions associées aux tools de chaque item de la liste.

* On peut lui passer des paramères grace à la propriété _onclickArg de l'objet {ObjListe} que l'on ajoute.
* @see #_onclickArg
* @type handler []
*/
_handlers : null,


/**
* Fonction appellée par le constructeur
* @private
* @param {Object} config
* @return {void}
*/
init : function ( config )
{
ApplyConfig ( config, this );

this._element = YAHOO.ext.Element.get ( this._id );

if ( this._element == null )
{
this._element = YAHOO.ext.DomHelper.append ( document.body, {tag:'div', id:this._id}, true );
}

this._element.setAbsolutePositioned();

if ( this._css == null )
{
this._element.setBounds ( this.x, this.y, this.width, this.height );
}
else
{
this._element.addClass ( this._css );
}
this._element.addClass ( this._class );


this._mapObject = new YAHOO.ext.util.MixedCollection ( true );
this._mapObject.getKey = function ( el )
{
return el._libelle;
}

this._mapElement = new YAHOO.ext.util.MixedCollection ( true );
this._mapElement.getKey = function ( el )
{
return el.dom.getAttribute ( "id" );
//return el.dom.getAttribute ( "indice" );
}

this._mapSelected = new YAHOO.ext.util.MixedCollection ( true );
this._mapSelected.getKey = function ( el )
{
return el.dom.getAttribute ( "id" );
//return el.dom.getAttribute ( "indice" );
}

this._mapEvent = new YAHOO.ext.util.MixedCollection ( true );

this._selectedIndex = -1;
//console.log ("start :" + this._element.dom.childNodes.length);

},

/**
* Ajout d'un item à la liste.
*
* @param {ObjListe} object L'objet à ajouter à la liste.

* Soit une chaine de caractère soit un objet de type {ObjListe}.
* @return {void}
*/
Add : function ( object )
{
if ( typeof object != "object" )
{
object = new ObjListe ({_libelle:object});
}

this._mapObject.add ( object );
this.PaintOneObject ( object );
},

/**
* Suppression de l'item dont le texte est passé en paramètre.
* @return {void} *
* @param {String} item Le libellede l'item à supprimer.
*/
Remove : function ( item )
{
this._mapObject.removeKey ( item );
this.Repaint ();
},

/**
* Suppression de tous les éléments de la liste.
* @return {void}
*/
Clear : function ()
{
this._element.update ("");
this._mapElement.clear ();
this._mapObject.clear ();
},


/**
* Redessine tous les items de la liste à la suite d'une suppression d'élément.
* @private
* @return {void}
*/
Repaint : function ()
{
this._element.update ("");
this._mapElement.clear ();

for ( var i=0; i<this._mapObject.getCount(); i++ )
{
var obj = this._mapObject.items [i];
this.PaintOneObject ( obj );
}
},
/**
* Dessin d'un item de la liste. Cette fonction est appellée lors de l'ajout d'un item.
* @see #Add
* @private
* @param {Object} obj
*/
PaintOneObject : function ( obj )
{
console.warn ( "List::PaintOneObject" );

var val = "";
if ( typeof obj == "object" )
{
val = obj._libelle;
}
else
{
val = obj;
}

var html = "";
var classe = "";
var style = "";

//Couleurs alternées.
if ( this._mapElement.getCount() % 2 == 0 )
{
classe = "paire";
}
else
{
classe = "impaire";
}


//Class du dernier item
for ( var ind=0; ind<this._mapElement.getCount(); ind++ )
{
if ( ind != this._mapObject.getCount () -1 )
{
style = "border-bottom : 0px solid black;";
this._mapElement.get ( ind ).setStyle ( "border-bottom", "0px" );
}
}

//Dessin du trait bas du dernier élément.
if ( this._mapElement.getCount() == this._mapObject.getCount () -1 )
{
style = "border-bottom : 1px solid black;";
}

var dh = YAHOO.ext.DomHelper;

var divItem = dh.append ( this._element.dom, {tag:'div', style:style}, true );
divItem.addClass ( "cell" );
divItem.addClass ( classe );//OK

style = "width:100%;";
var divTable = dh.append ( divItem.dom, { tag:'table', style:style}, true );
divTable.dom.setAttribute ( "cellpadding", "0" );
divTable.dom.setAttribute ( "cellspacing", "0" );//OK

var divTBody = dh.append ( divTable.dom, {tag:'tbody'}, true );
var divTr = dh.append ( divTBody.dom, { tag:'tr' }, true );//OK

style = "text-align:left;";//z-index:-10;
var divTd = dh.append ( divTr.dom, { tag:'td', style:style, indice:this._mapElement.getCount(), html:val }, true );//OK

if ( obj._configTool != null )
{
style = "width:" + (obj._configTool.length * 22) + "px;text-align:right;";
var tdTools = dh.append ( divTr.dom, { tag:'td', style:style }, true );

style = "text-align:right;font-size:2px;";
var tableTool = dh.append ( tdTools.dom, { tag:'table', style:style}, true );
tableTool.dom.setAttribute ( "cellpadding", "0" );
tableTool.dom.setAttribute ( "cellspacing", "0" );

var tbodyTool = dh.append ( tableTool.dom, {tag:'tbody'}, true );
var trTool = dh.append ( tbodyTool.dom, {tag:'tr'}, true );


for ( var ind=0; ind<obj._configTool.length; ind++ )
{
var tdTool = dh.append ( trTool.dom, {tag:'td'}, true );
tdTool.dom.setAttribute ( "indice", this._mapElement.getCount() );
//console.log ("_configTool : %o", obj._configTool [ind]);

if ( obj._configTool [ind]._alt != null )
{
//console.log (obj._configTool [ind]._alt);
//tdTool.dom.setAttribute ( "alt", obj._configTool [ind]._alt );

new YAHOO.widget.Tooltip("tt"+this._mapElement.getCount()+"_"+ind,
{ context:tdTool.dom,
text:obj._configTool [ind]._alt });


}

tdTool.addClass ( obj._configTool [ind].css );

if ( obj._configTool [ind]._arguments != null )
{
for ( var arg=0; arg<obj._configTool [ind]._arguments.length; arg++ )
{
tdTool.dom.setAttribute ( "arg_"+arg, obj._configTool [ind]._arguments [arg] );
}
}
//tdTool.dom.setAttribute ("handler", obj._configTool [ind].handler);
var _scope = divItem;
if ( obj._configTool [ind].scope != null )
{
_scope = obj._configTool [ind].scope;
//console.log ("scope : %o", _scope);
}
//
tdTool.on ( "click", this._handlers [ ind ].createDelegate( _scope, obj._configTool [ind]._arguments ), _scope );
//tdTool.on ( "click", this._handlers [ ind ].createCallback( _scope, obj._configTool [ind]._arguments ), _scope );
//myElement.on("click", myObject.clickHandler.createCallback("foo", {bar:"bletch"}), myObject)
}
}

divItem.dom.setAttribute ( "indice", this._mapElement.getCount() );

if ( this._highlightOnmouseover == true )
{
divItem.addClassOnOver ( "mouseover" );
}
divItem.on ("click", this.ClickHandler, this );

for ( var j=0; j<this._mapEvent.getCount(); j++ )
{

//console.log ("evt");
var evt = this._mapEvent.get ( j );
divItem.on ( evt._name,
function()
{
evt._handler.apply ( evt._scope || this, [this] || []);
},
divItem );
}

divItem.dom.setAttribute ( "_value", this._mapObject.get ( this._mapElement.getCount() )._libelle );

//Implementation du OnClick sur l'item.
if ( this._onclick != null && obj._onclickArg != null )
{
divItem.on ( "click", this._onclick.createDelegate( window, obj._onclickArg ), window );
}

this._mapElement.add ( divItem );
},




//Fonction interne qui met a jour sur le click la variable selectedIndex.
//On peut lui coder d'autre chose
/**
* @private
* @param {Object} evt
*/
ClickHandler : function ( evt )
{
console.log ( evt );
var indice = evt.target.getAttribute ( "indice" );
var element = this._mapElement.get ( indice );
console.log ( element );

//On est en mode sélection.
if ( this._selectable == true || this._multiselectable == true )
{
//On supprime toutes les classes selected
this._mapElement.each ( this.RemoveClassSelected, this );

//Mode selection simple
if ( this._selectable == true && this._multiselectable == false )
{
this._mapSelected.clear ();

this._mapSelected.add ( element );

element.addClass ( "selected" );
this._selectedIndex = indice;
}

//Mode selection multiple
if ( this._multiselectable == true )
{
//Touche CTRL non enfoncée
if ( evt.ctrlKey == false )
{
this._mapSelected.clear ();

this._mapSelected.add ( element );

element.addClass ( "selected" );
this._selectedIndex = indice;

}
//Touche CTRL enfoncée
else
{
if ( this._mapSelected.contains ( element ) )
{
console.log ( "avant : %d", this._mapSelected.getCount() );
this._mapSelected.remove ( element );
console.log ( "apres : %d", this._mapSelected.getCount() );
}
else
{
this._mapSelected.add ( element );
}

this._mapSelected.each ( this.AddClassSelected, this );
}

}
}





},




/**
* Ajout de l'item de la liste de son état selected.
* @private
* @param {YAHOO.ext.Element} el L'element de la liste pour lequel on veut ajouter le style selectionne
*/
AddClassSelected : function ( el )
{
el.addClass ( "selected" );
},

/**
* Suppression de l'item de la liste de son état selected.
* @private
* @param {YAHOO.ext.Element} el L'element de la liste pour lequel on veut supprimer le style selectionne
*/
RemoveClassSelected : function ( el )
{
el.removeClass ( "selected" );
},


/**
* Retourne l'index de l'élément sélectionné seulement si la liste est selectable.
* @return {int} L'index sélectionné.
*/
GetSelectedIndex : function ()
{
if ( this._selectable == true && this._mapSelected.getCount () == 1 )
{
return parseInt ( this._selectedIndex );
}
return -1;
},

/**
* Retourne les indexes des éléments sélectionnés seulement si la liste est mulitselectable.
* @return {int[]} Le tableau des indices selectionnes
*/
GetSelectedIndexes : function ()
{
var arrInd = [];
if ( this._multiselectable == true )
{
for ( var i=0; i<this._mapSelected.getCount (); i++ )
{
var obj = this._mapSelected.items [i];
var indice = obj.dom.getAttribute ( "indice" );
arrInd.push ( parseInt( indice ) );
}
arrInd.sort ();
return arrInd;
}
return arrInd;
},


/**
* Sélectionne l'index passé en paramètre.
* @param {Object} index L'index à sélectionner.
*/
SetSelectedIndex : function( index )
{
console.error ( "List::SetSelectedIndex -> Tester selectable et multiselectable et ajouter à mapSelect" );
this._selectedIndex = index;
},


/**
* Permet d'ajouter à chacun des items de la liste un évenement qui sera appellé sans paramètres.
* Pour passer des paramètres à un handler sur un item de la liste, utiliser la propriété _onclick.
* @see #_onclick
* @param {Object} eventName Le type de l'evenement.
* @param {Object} handler La fonction a appellée lors de l'évenement.
* @param {Object} scope Le scope à partir duquel le handler est appellé.
*/
on : function ( eventName, handler, scope )
{
var evt = new ObjEvent ( {_name:eventName,_handler:handler, _scope:scope} );

this._mapEvent.add ( eventName, evt );

/*for ( var i=0; i<this._mapElement.getCount(); i++ )
{
var elem = this._mapElement.get ( i );


elem.on ( eventName,
function()
{
handler.apply ( scope || this, [this] || []);
},
elem );


}*/
this.Paint ();
}


};




ObjEvent = function ( config )
{
this.init ( config );
};

ObjEvent.prototype=
{
_name : null,
_scope : null,
_handler : null,
_params : null,

init : function ( config )
{
ApplyConfig ( config, this );
}

}




//configTool = [{ handler : null, css : null, argument : null }];
/**
*
* @constructor
* Création d'un nouvel item de Liste.
* L'utilité de cet objet est d'associer à chaque item un outil (tool) représenté par un icon qui permet d'exécuter une fonction et de lui passer des arguments.
*
* @param {Object} config configuration options
*/
ObjListe = function ( config )
{
this.init ( config );
}
ObjListe.prototype =
{

/**
* Le libellé de l'item qui apparaitra dans la liste.

* C'est le seul membre obligatoire de cet Objet.

* Toutefois, si vous n'avez qu'une chaine à ajouter à la liste, ce n'est pas la peine d'utiliser cet objet.
* @see #List.Add
* @type String
*/
_libelle : null,


/**
* Tableau contenant chacun des tools associés à l'item courant.
Il contient son apparence, un handler, des arguments.
* @type Object []
*/
_configTool : null,


/**
* Tableau des arguments qui seront passés à la fonction _onclick de l'objet List.
* @see #List
* @type String []
*/
_onclickArg : null,



init : function ( config )
{
ApplyConfig ( config, this );
}
}



index.html






<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"/>
<title>LISTES</title>

<link href="./js-lib/yui-ext/resources/css/basic-dialog.css" type="text/css" rel="stylesheet">
<link href="./js-lib/yui-ext/resources/css/button.css" type="text/css" rel="stylesheet">
<link href="./js-lib/yui-ext/resources/css/resizable.css" rel="stylesheet" type="text/css" />
<link href="./css/list.css" rel="stylesheet" type="text/css" />



<script type="text/javascript" src="./js-lib/yui/build/yahoo/yahoo-min.js"></script>
<script type="text/javascript" src="./js-lib/yui/build/event/event-min.js"></script>
<script type="text/javascript" src="./js-lib/yui/build/dom/dom-min.js"></script>
<script type="text/javascript" src="./js-lib/yui/build/dragdrop/dragdrop-min.js"></script>
<script type="text/javascript" src="./js-lib/yui/build/connection/connection-min.js"></script>

<script type="text/javascript" src="./js-lib/yui-ext/yui-ext.js"></script>

<script type="text/javascript" src="./js-lib/BGeocoder/geonamesData.js"></script>
<script type="text/javascript" src="./js-lib/BGeocoder/jsr_class.js"></script>
<script type="text/javascript" src="./js-lib/BGeocoder/BGeocoder.js"></script>
<script type="text/javascript" src="./js-lib/BGeocoder/lib_navig.js"></script>
<script type="text/javascript" src="./js-lib/BGeocoder/lib_xhr.js"></script>
<script type="text/javascript" src="./js-lib/BGeocoder/json.js"></script>

<script type="text/javascript" src="./components/component.js"></script>
<script type="text/javascript" src="./components/container.js"></script>
<script type="text/javascript" src="./components/label.js"></script>
<script type="text/javascript" src="./components/button.js"></script>
<script type="text/javascript" src="./components/textfield.js"></script>
<script type="text/javascript" src="./components/panel.js"></script>
<script type="text/javascript" src="./visual/drawer.js"></script>
<script type="text/javascript" src="./visual/visualX.js"></script>


<script type="text/javascript" src="./function.js"></script>
<script type="text/javascript" src="./list.js"></script>


<style>
body
{
font-family : Sans-serif;
}



</style>

<style>
.drawer .selection
{
position:absolute;
border:1px solid #ff0000;
font-size:1px;
display:none;
}

</style>
</head>


<body >


<div id="list" style="border:1px solid red;"></div>
</div>


<script type="text/javascript">

//var visualX = new VisualX ();




function OnItemClick ( evt )
{
console.log ( "OnItemClick %o", evt.target );
console.log ( "this %o", this );
}

var liste = new List ( {_id:'list', x:50,y:100,width:250,height:220,
_class : 'liste',
_selectable : true,
_multiselectable : true,
_onclick : OnListClick,
_highlightOnmouseover: true,
_handlers : [OnItemClick, OnItemClick]});




//liste.on ( "click", OnListClick, this );


liste.Add ( new ObjListe ({_libelle:'le libelle', _configTool:[{css:'delete'},{css:'delete'}]}) );
liste.Add ( "Encore" );
liste.Add ( "Un autre" );

liste.Add ( new ObjListe ({ _libelle : 'OnClick',
_onclickArg : ['salut0', 'salut1'],
_configTool : null}) );



function OnListClick ( arg0, arg1 )
{
console.log ( "OnListeClick %o %o", arg0, arg1 );
}
/*liste.Add ( "das it work" );
liste.Add ( "Encore" );
liste.Add ( "Un de plus" );*/










/*






var container = new XPanel ( 'main0' );
var label = new XLabel ( 'idLab', 'un cool label' );
var bouton = new XButton ( 'idBut', 'un bouton' );
var textfield = new XTextField ( 'idText', 'une zone de saisie' );

container.SetBounds (450, 150, 600, 300 );
container._element.setAbsolutePositioned ();

container.Add ( label );
container.Add ( textfield );
container.Add ( bouton );

label.SetBorderWidth ( "1px dashed blue" );
label.SetBounds ( 30, 10, 100, 25 );



textfield.SetBorderWidth ( "1px solid #000000" );
textfield.SetBounds ( 300, 50, 150, 25 );

bouton.SetBorderWidth ( "1px solid #000000" );
bouton.SetBounds ( 450, 50, 100, 25 );
bouton.AddActionListener ( "click", OnClick );







function OnClick ( evt )
{
alert ( textfield.GetText () );
}


var elem = new YAHOO.ext.Element ( "input" , true );

elem.setStyle ( "border", "1px solid black" );


console.log ("elem : %o", elem);*/
</script>

</body>

</html>






css/list.css






.liste
{
padding:0px;
overflow:auto;
border : 1px solid black;
font-size : 14px;
}

.liste .paire
{
background-color:#d6d7ff;
}

.liste .impaire
{
background-color:#ffffff;
}

.liste .cell
{
border-top : 1px solid black;
border-left : 1px solid black;
border-right : 1px solid black;
padding : 2px;
}

.liste .mouseover
{
background-color:#a5a6ff;
}

.liste .selected
{
background-color:#a5a6ff;
}

.liste .delete
{
background-image:url(./delete.png);
background-repeat : no-repeat;
width:15px;
height:14px;
}

tryanDLS
22 Feb 2007, 7:39 AM
That's a whole lot of code to try and digest. Can you boil that down to a simple example that illustrates the problem?

simeon
22 Feb 2007, 8:10 AM
The blue border is probably the selection of a form element or an anchor that is in his div.
Ctrl clicking on a div doesn't prevent the stuff in his div from reacting to the click as well.
Event trapping will probably help here.

This is the default behavior for selection of forms and links that is added by the browsers.

In IE, I think you can prevent the focus of a link or button. I also think there is a way to prevent the border using css, but I can't recall the exact details for that. You might check the w3 spec if this is infact the case.

http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/hidefocus.asp