1 /** 2 * color picker 3 * @author yiminghe@gmail.com 4 */ 5 KISSY.add("editor/plugin/color/colorPicker/dialog", function (S, Editor, Overlay4E) { 6 var map = S.map, 7 DOM = S.DOM; 8 9 DOM.addStyleSheet("" + 10 ".ks-editor-color-advanced-picker-left {" + 11 "float:left;" + 12 "display:inline;" + 13 "margin-left:10px;" + 14 "}" + 15 16 ".ks-editor-color-advanced-picker-right {" + 17 "float:right;" + 18 "width:50px;" + 19 "display:inline;" + 20 "margin:13px 10px 0 0;" + 21 "cursor:crosshair;" + 22 "}" + 23 "" + 24 ".ks-editor-color-advanced-picker-right a {" + 25 "height:2px;" + 26 "line-height:0;" + 27 "fontSize:0;" + 28 "display:block;" + 29 "}" + 30 "" + 31 32 ".ks-editor-color-advanced-picker-left ul{" + 33 "float:left;" + 34 "}" + 35 ".ks-editor-color-advanced-picker-left li,.ks-editor-color-advanced-picker-left a{" + 36 "overflow:hidden;" + 37 "width:15px;" + 38 "height:16px;" + 39 "line-height:0;" + 40 "fontSize:0;" + 41 "display:block;" + 42 "}" + 43 ".ks-editor-color-advanced-picker-left a:hover{" + 44 "width:13px;height:13px;border:1px solid white;" + 45 "}" + 46 "" + 47 ".ks-editor-color-advanced-indicator {" + 48 "margin-left:10px;" + 49 "*zoom:1;" + 50 "display:inline-block;" + 51 "*display:inline;" + 52 "width:68px;" + 53 "height:24px;" + 54 "vertical-align:middle;" + 55 "line-height:0;" + 56 "overflow:hidden;" + 57 "}", "ks-editor-color-advanced"); 58 59 //获取颜色数组 60 function getData(color) { 61 if (S.isArray(color)) return color; 62 var re = RegExp; 63 if (/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.test(color)) { 64 //#rrggbb 65 return map([ re['$1'], re['$2'], re['$3'] ], function (x) { 66 return parseInt(x, 16); 67 }); 68 } else if (/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.test(color)) { 69 //#rgb 70 return map([ re['$1'], re['$2'], re['$3'] ], function (x) { 71 return parseInt(x + x, 16); 72 }); 73 } else if (/^rgb\((.*),(.*),(.*)\)$/i.test(color)) { 74 //rgb(n,n,n) or rgb(n%,n%,n%) 75 return map([ re['$1'], re['$2'], re['$3'] ], function (x) { 76 return x.indexOf("%") > 0 ? parseFloat(x, 10) * 2.55 : x | 0; 77 }); 78 } 79 return undefined; 80 } 81 82 //refer:http://www.cnblogs.com/cloudgamer/archive/2009/03/11/color.html 83 //http://yiminghe.javaeye.com/blog/511589 84 //获取颜色梯度方法 85 var ColorGrads = (function () { 86 //获取颜色梯度数据 87 function getStep(start, end, step) { 88 var colors = []; 89 start = getColor(start); 90 end = getColor(end); 91 var stepR = (end[0] - start[0]) / step, 92 stepG = (end[1] - start[1]) / step, 93 stepB = (end[2] - start[2]) / step; 94 //生成颜色集合 95 for (var i = 0, r = start[0], g = start[1], b = start[2]; i < step; i++) { 96 colors[i] = [r, g, b]; 97 r += stepR; 98 g += stepG; 99 b += stepB; 100 } 101 colors[i] = end; 102 //修正颜色值 103 return map(colors, function (x) { 104 return map(x, function (x) { 105 return Math.min(Math.max(0, Math.floor(x)), 255); 106 }); 107 }); 108 } 109 110 //获取颜色数据 111 var frag; 112 113 function getColor(color) { 114 var ret = getData(color); 115 if (ret === undefined) { 116 if (!frag) { 117 frag = document.createElement("textarea"); 118 frag.style.display = "none"; 119 DOM.prepend(frag, document.body); 120 } 121 try { 122 frag.style.color = color; 123 } catch (e) { 124 return [0, 0, 0]; 125 } 126 127 if (document.defaultView) { 128 ret = getData(document.defaultView.getComputedStyle(frag, null).color); 129 } else { 130 color = frag.createTextRange()['queryCommandValue']("ForeColor"); 131 ret = [ color & 0x0000ff, (color & 0x00ff00) >>> 8, (color & 0xff0000) >>> 16 ]; 132 } 133 } 134 return ret; 135 } 136 137 138 return function (colors, step) { 139 var ret = [], len = colors.length; 140 if (step === undefined) { 141 step = 20; 142 } 143 if (len == 1) { 144 ret = getStep(colors[0], colors[0], step); 145 } else if (len > 1) { 146 for (var i = 0, n = len - 1; i < n; i++) { 147 var t = step[i] || step; 148 var steps = getStep(colors[i], colors[i + 1], t); 149 i < n - 1 && steps.pop(); 150 ret = ret.concat(steps); 151 } 152 } 153 return ret; 154 } 155 })(); 156 157 function padding2(x) { 158 x = "0" + x; 159 var l = x.length; 160 return x.slice(l - 2, l); 161 } 162 163 function hex(c) { 164 c = getData(c); 165 return "#" + padding2(c[0].toString(16)) 166 + padding2(c[1].toString(16)) 167 + padding2(c[2].toString(16)); 168 } 169 170 var pickerHtml = "<ul>" + 171 map(ColorGrads([ "red", "orange", "yellow", "green", "cyan", "blue", "purple" ], 5), 172 function (x) { 173 return map(ColorGrads([ "white", "rgb(" + x.join(",") + ")" , "black" ], 5), 174 function (x) { 175 return "<li><a style='background-color" + ":" + hex(x) + "' href='#'></a></li>"; 176 }).join(""); 177 }).join("</ul><ul>") + "</ul>", 178 panelHtml = "<div class='ks-editor-color-advanced-picker'>" + 179 "<div class='ks-clear'>" + 180 "<div class='ks-editor-color-advanced-picker-left'>" + 181 pickerHtml + 182 "</div>" + 183 "<div class='ks-editor-color-advanced-picker-right'>" + 184 "</div>" + 185 "</div>" + 186 "<div style='padding:10px;'>" + 187 "<label>" + 188 "颜色值: " + 189 "<input style='width:100px' class='ks-editor-color-advanced-value'/>" + 190 "</label>" + 191 "<span class='ks-editor-color-advanced-indicator'></span>" + 192 "</div>" + 193 "</div>", 194 footHtml = "<div style='padding:5px 20px 20px;'>" + 195 "<a class='ks-editor-button ks-editor-color-advanced-ok ks-inline-block'>确定</a>" + 196 " " + 197 "<a class='ks-editor-button ks-editor-color-advanced-cancel ks-inline-block'>取消</a>" + 198 "</div>"; 199 200 function ColorPicker(editor) { 201 this.editor = editor; 202 this._init(); 203 } 204 205 var addRes = Editor.Utils.addRes, destroyRes = Editor.Utils.destroyRes; 206 207 S.augment(ColorPicker, { 208 _init:function () { 209 var self = this; 210 211 self.dialog = new Overlay4E.Dialog({ 212 mask:true, 213 headerContent:"颜色拾取器", 214 bodyContent:panelHtml, 215 footerContent:footHtml, 216 autoRender:true, 217 width:"550px" 218 }); 219 var win = self.dialog, 220 body = win.get("body"), 221 foot = win.get("footer"), 222 indicator = body.one(".ks-editor-color-advanced-indicator"), 223 indicatorValue = body.one(".ks-editor-color-advanced-value"), 224 left = body.one(".ks-editor-color-advanced-picker-left"), 225 right = body.one(".ks-editor-color-advanced-picker-right"), 226 ok = foot.one(".ks-editor-color-advanced-ok"), 227 cancel = foot.one(".ks-editor-color-advanced-cancel"); 228 229 ok.on("click", function (ev) { 230 var v = S.trim(indicatorValue.val()), 231 cmd = self.cmd; 232 if (!/^#([a-f0-9]{1,2}){3,3}$/i.test(v)) { 233 alert("请输入正确的颜色代码"); 234 return; 235 } 236 //先隐藏窗口,使得编辑器恢复焦点,恢复原先range 237 self.hide(); 238 setTimeout(function () { 239 self.editor.execCommand(cmd, indicatorValue.val()); 240 }, 0); 241 ev.halt(); 242 }); 243 244 245 indicatorValue.on("change", function () { 246 var v = S.trim(indicatorValue.val()); 247 if (!/^#([a-f0-9]{1,2}){3,3}$/i.test(v)) { 248 alert("请输入正确的颜色代码"); 249 return; 250 } 251 indicator.css("background-color", v); 252 }); 253 254 255 cancel.on("click", function (ev) { 256 self.hide(); 257 ev && ev.halt(); 258 }); 259 body.on("click", function (ev) { 260 ev.halt(); 261 var t = new S.Node(ev.target); 262 if (t.nodeName() == "a") { 263 var c = hex(t.css("background-color")); 264 if (left.contains(t))self._detailColor(c); 265 indicatorValue.val(c); 266 indicator.css("background-color", c); 267 } 268 }); 269 addRes.call(self, ok, indicatorValue, cancel, body, self.dialog); 270 271 var defaultColor = "#FF9900"; 272 self._detailColor(defaultColor); 273 indicatorValue.val(defaultColor); 274 indicator.css("background-color", defaultColor); 275 }, 276 277 _detailColor:function (color) { 278 var self = this, 279 win = self.dialog, 280 body = win.get("body"), 281 detailPanel = body.one(".ks-editor-color-advanced-picker-right"); 282 283 detailPanel.html(map(ColorGrads(["#ffffff", color, "#000000"], 40), 284 function (x) { 285 return "<a style='background-color:" + hex(x) + "'></a>"; 286 }).join("")); 287 }, 288 show:function (cmd) { 289 this.cmd = cmd; 290 this.dialog.show(); 291 }, 292 hide:function () { 293 this.dialog.hide(); 294 }, 295 destroy:function () { 296 destroyRes.call(this); 297 } 298 }); 299 300 return ColorPicker; 301 }, { 302 requires:['editor', '../../overlay/'] 303 });