Yikes! Усі ці обхідні шляхи привели мене до висновку, що прапорець HTML начебто відстійний, якщо ви хочете його стилізувати.
Як попередження, це не реалізація CSS. Я просто думав, що поділюсь вирішенням, з яким я придумав, на випадок, якщо хтось інший вважатиме це корисним
Я використовував canvas
елемент HTML5 .
Перевагою цього є те, що вам не доведеться використовувати зовнішні зображення і, ймовірно, ви можете зберегти деяку пропускну здатність.
Мінус полягає в тому, що якщо веб-переглядач з якихось причин не може виправити його належним чином, тоді немає жодного запасного варіанту. Незважаючи на те, чи залишається це питання у 2017 році, є дискусійним.
Оновлення
Я знайшов старий код досить некрасивим, тому вирішив дати його переписати.
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;
}
});
Ось робоча демонстрація .
Нова версія використовує прототипи та диференційоване успадкування для створення ефективної системи для створення прапорців. Щоб створити прапорець:
var my_checkbox = Checkbox.create();
Це негайно додасть прапорець у DOM та підключить події. Щоб запитати, чи встановлено прапорець:
my_checkbox.is_checked(); // True if checked, else false
Також важливо зазначити, що я позбувся циклу.
Оновлення 2
Щось я нехтував зазначити в останньому оновлення, це те, що використання полотна має більше переваг, ніж просто виготовлення прапорця, який виглядає, проте ви хочете, щоб воно виглядало. Ви також можете створити прапорці для багатьох держав , якщо цього хочете.
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;
}
});
Я трохи змінив Checkbox
використаний в останньому фрагменті, щоб він був більш загальним, що дозволяє "розширити" його за допомогою прапорця, який має 3 стани. Ось демонстрація . Як бачите, він вже має більше функціональних можливостей, ніж вбудований прапорець.
Що слід враховувати, коли ви обираєте JavaScript та CSS.
Старий, погано розроблений код
Робоча демонстрація
Спочатку встановіть полотно
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'));
Далі придумайте спосіб оновити полотно.
(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
})();
Остання частина - зробити її інтерактивною. На щастя, це досить просто:
canvas.onclick = function(){
checked = !checked;
}
Тут можуть виникнути проблеми в IE через їх дивну модель обробки подій у JavaScript.
Я сподіваюся, що це комусь допоможе; це безумовно відповідало моїм потребам.