Astaga! Semua solusi ini telah membawa saya pada kesimpulan bahwa kotak centang HTML agak menyebalkan jika Anda ingin menata.
Sebagai peringatan, ini bukan implementasi CSS. Saya hanya berpikir saya akan berbagi solusi yang saya buat kalau-kalau ada orang lain yang merasa berguna.
Saya menggunakan canvas
elemen HTML5 .
Keuntungannya adalah Anda tidak harus menggunakan gambar eksternal dan mungkin dapat menghemat bandwidth.
Kelemahannya adalah jika browser karena alasan tertentu tidak dapat merendernya dengan benar, maka tidak ada fallback. Meskipun apakah ini tetap menjadi masalah di 2017 masih bisa diperdebatkan.
Memperbarui
Saya menemukan kode lama cukup jelek, jadi saya memutuskan untuk menulis ulang.
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;
}
});
Ini demo yang berfungsi .
Versi baru menggunakan prototipe dan pewarisan diferensial untuk membuat sistem yang efisien untuk membuat kotak centang. Untuk membuat kotak centang:
var my_checkbox = Checkbox.create();
Ini akan segera menambahkan kotak centang ke DOM dan menghubungkan acara. Untuk menanyakan apakah kotak centang dicentang:
my_checkbox.is_checked(); // True if checked, else false
Juga penting untuk dicatat adalah bahwa saya menyingkirkan loop.
Perbarui 2
Sesuatu yang saya lalai untuk menyebutkan dalam pembaruan terakhir adalah bahwa menggunakan kanvas memiliki kelebihan lebih dari sekadar membuat kotak centang yang terlihat namun Anda ingin melihatnya. Anda juga bisa membuat kotak centang multi-negara , jika Anda mau.
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;
}
});
Saya sedikit memodifikasi yang Checkbox
digunakan dalam cuplikan terakhir sehingga lebih umum, sehingga memungkinkan untuk "memperpanjang" dengan kotak centang yang memiliki 3 status. Ini demo . Seperti yang Anda lihat, itu sudah memiliki lebih banyak fungsi daripada kotak centang bawaan.
Sesuatu untuk dipertimbangkan ketika Anda memilih antara JavaScript dan CSS.
Kode lama, tidak dirancang dengan baik
Demo yang Bekerja
Pertama, atur kanvas
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'));
Selanjutnya, cari cara untuk memiliki pembaruan kanvas itu sendiri.
(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
})();
Bagian terakhir adalah membuatnya interaktif. Untungnya, ini sangat sederhana:
canvas.onclick = function(){
checked = !checked;
}
Di sinilah Anda mungkin memiliki masalah di IE, karena model penanganan peristiwa aneh mereka dalam JavaScript.
Saya harap ini membantu seseorang; itu pasti sesuai dengan kebutuhan saya.