Oui! Toutes ces solutions de contournement m'ont amené à la conclusion que le type de case à cocher HTML est nul si vous voulez le styliser.
À titre d'avertissement, ce n'est pas une implémentation CSS. Je pensais juste partager la solution de contournement que j'ai trouvée au cas où quelqu'un d'autre pourrait la trouver utile.
J'ai utilisé l' canvas
élément HTML5 .
L'avantage est que vous n'avez pas à utiliser d'images externes et que vous pouvez probablement économiser de la bande passante.
L'inconvénient est que si un navigateur ne peut pas le rendre correctement, il n'y a pas de solution de rechange. Bien que cela reste un problème en 2017 est discutable.
Mise à jour
J'ai trouvé l'ancien code assez moche, alors j'ai décidé de le réécrire.
Object.prototype.create = function(args){
var retobj = Object.create(this);
retobj.constructor(args || null);
return retobj;
}
var Checkbox = Object.seal({
width: 0,
height: 0,
state: 0,
document: null,
parent: null,
canvas: null,
ctx: null,
/*
* args:
* name default desc.
*
* width 15 width
* height 15 height
* document window.document explicit document reference
* target this.document.body target element to insert checkbox into
*/
constructor: function(args){
if(args === null)
args = {};
this.width = args.width || 15;
this.height = args.height || 15;
this.document = args.document || window.document;
this.parent = args.target || this.document.body;
this.canvas = this.document.createElement("canvas");
this.ctx = this.canvas.getContext('2d');
this.canvas.width = this.width;
this.canvas.height = this.height;
this.canvas.addEventListener("click", this.ev_click(this), false);
this.parent.appendChild(this.canvas);
this.draw();
},
ev_click: function(self){
return function(unused){
self.state = !self.state;
self.draw();
}
},
draw_rect: function(color, offset){
this.ctx.fillStyle = color;
this.ctx.fillRect(offset, offset,
this.width - offset * 2, this.height - offset * 2);
},
draw: function(){
this.draw_rect("#CCCCCC", 0);
this.draw_rect("#FFFFFF", 1);
if(this.is_checked())
this.draw_rect("#000000", 2);
},
is_checked: function(){
return !!this.state;
}
});
Voici une démo qui fonctionne .
La nouvelle version utilise des prototypes et l'héritage différentiel pour créer un système efficace de création de cases à cocher. Pour créer une case à cocher:
var my_checkbox = Checkbox.create();
Cela ajoutera immédiatement la case à cocher au DOM et connectera les événements. Pour savoir si une case est cochée:
my_checkbox.is_checked(); // True if checked, else false
Il est également important de noter que je me suis débarrassé de la boucle.
Update 2
Quelque chose que j'ai négligé de mentionner dans la dernière mise à jour est que l'utilisation du canevas a plus d'avantages que de simplement créer une case à cocher qui ressemble à ce que vous voulez. Vous pouvez également créer des cases à cocher à plusieurs états , si vous le souhaitez.
Object.prototype.create = function(args){
var retobj = Object.create(this);
retobj.constructor(args || null);
return retobj;
}
Object.prototype.extend = function(newobj){
var oldobj = Object.create(this);
for(prop in newobj)
oldobj[prop] = newobj[prop];
return Object.seal(oldobj);
}
var Checkbox = Object.seal({
width: 0,
height: 0,
state: 0,
document: null,
parent: null,
canvas: null,
ctx: null,
/*
* args:
* name default desc.
*
* width 15 width
* height 15 height
* document window.document explicit document reference
* target this.document.body target element to insert checkbox into
*/
constructor: function(args){
if(args === null)
args = {};
this.width = args.width || 15;
this.height = args.height || 15;
this.document = args.document || window.document;
this.parent = args.target || this.document.body;
this.canvas = this.document.createElement("canvas");
this.ctx = this.canvas.getContext('2d');
this.canvas.width = this.width;
this.canvas.height = this.height;
this.canvas.addEventListener("click", this.ev_click(this), false);
this.parent.appendChild(this.canvas);
this.draw();
},
ev_click: function(self){
return function(unused){
self.state = !self.state;
self.draw();
}
},
draw_rect: function(color, offsetx, offsety){
this.ctx.fillStyle = color;
this.ctx.fillRect(offsetx, offsety,
this.width - offsetx * 2, this.height - offsety * 2);
},
draw: function(){
this.draw_rect("#CCCCCC", 0, 0);
this.draw_rect("#FFFFFF", 1, 1);
this.draw_state();
},
draw_state: function(){
if(this.is_checked())
this.draw_rect("#000000", 2, 2);
},
is_checked: function(){
return this.state == 1;
}
});
var Checkbox3 = Checkbox.extend({
ev_click: function(self){
return function(unused){
self.state = (self.state + 1) % 3;
self.draw();
}
},
draw_state: function(){
if(this.is_checked())
this.draw_rect("#000000", 2, 2);
if(this.is_partial())
this.draw_rect("#000000", 2, (this.height - 2) / 2);
},
is_partial: function(){
return this.state == 2;
}
});
J'ai légèrement modifié l' Checkbox
utilisé dans le dernier extrait pour qu'il soit plus générique, permettant de "l'étendre" avec une case à cocher qui a 3 états. Voici une démo . Comme vous pouvez le voir, il a déjà plus de fonctionnalités que la case à cocher intégrée.
Quelque chose à considérer lorsque vous choisissez entre JavaScript et CSS.
Code ancien et mal conçu
Démo de travail
Tout d'abord, créez une toile
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
checked = 0; // The state of the checkbox
canvas.width = canvas.height = 15; // Set the width and height of the canvas
document.body.appendChild(canvas);
document.body.appendChild(document.createTextNode(' Togglable Option'));
Ensuite, imaginez un moyen de mettre à jour le canevas lui-même.
(function loop(){
// Draws a border
ctx.fillStyle = '#ccc';
ctx.fillRect(0,0,15,15);
ctx.fillStyle = '#fff';
ctx.fillRect(1, 1, 13, 13);
// Fills in canvas if checked
if(checked){
ctx.fillStyle = '#000';
ctx.fillRect(2, 2, 11, 11);
}
setTimeout(loop, 1000/10); // Refresh 10 times per second
})();
La dernière partie est de le rendre interactif. Heureusement, c'est assez simple:
canvas.onclick = function(){
checked = !checked;
}
C'est là que vous pourriez avoir des problèmes dans IE, en raison de leur modèle de gestion d'événements étrange en JavaScript.
J'espère que ça aidera quelqu'un; il convenait définitivement à mes besoins.