diff --git a/content/blog/2015-03-26-porting-carrier-101.md b/content/blog/2015-03-26-porting-carrier-101.md new file mode 100644 index 0000000..a73c161 --- /dev/null +++ b/content/blog/2015-03-26-porting-carrier-101.md @@ -0,0 +1,27 @@ +title: ย้ายค่ายมือถือ 101 +date: Mar 26, 2015 +author: sipp11 +category: misc +tags: info +icon: briefcase +slug: ย้ายค่ายมือถือ-ข้อควรรู้ + + +การย้ายค่ายมือถือเป็นเรื่องง่ายในหลักการ แต่ความเป็นจริงนั้น มันก็มีข้อควรรู้ก่อนจะทำ เนื่องด้วยการย้ายค่ายนั้นจะใช้เวลาดำเนินการประมาณ 3-5 วันทำการ (อย่าลืม: ไม่รวมวันเสาร์ อาทิตย์ วันหยุด) สิ่งที่ต้องทำคร่าวๆ + +* จ่ายบิลที่คงค้างของค่ายที่ใช้อยู่ก่อน ซึ่งอาจจะไม่รวมเดือนสุดท้าย ซึ่งนั่นคือ บิลที่จะตามหลังมา + * ไม่ต้องแจ้งอะไร หรือแจ้งไปเค้าก็ไม่ได้ทำอะไรเพ่ิมเติมครับ เพราะการดำเนินการนี้เป็นหน้าที่ของค่ายใหม่ทั้งหมด +* ทำเรื่องย้ายเบอร์กับค่ายใหม่ + +ขั้นตอนง่ายๆนี้ จริงๆแล้วลำดับไม่สำคัญ แต่ควรจะจัดการให้เสร็จภายในวันเดียวกัน ไม่งั้นการย้ายค่ายจะช้าลง หลังจากนี้ก็เพียงรอเวลาค่ายใหม่แจ้งว่าการดำเนินการเสร็จสิ้นก็เปลี่ยน SIM ใช้งานได้ + +## What's the catch? + +ปัญหาเดียวของการย้ายค่ายนั่นคือ ช่วงเวลาครับ การปิดเบอร์มันมีเรื่องโง่ๆ เรื่องนึง คือ ค่ายอย่าง True (ผมไม่ทราบว่าค่ายอื่นทำอย่างนี้หรือไม่นะครับ แค่คิดว่าไม่ต่างกัน) จะคิดเงินรอบบิลสุดท้ายเต็มเดือน ไม่ว่าคุณจะยกเลิกมันวันไหนก็ตาม เช่น ถ้าคุณยกเลิกวันที่ 2 ของรอบบิล คุณจะต้องจ่ายเงินฟรีไปเกือบๆ 28 วันในรอบบิลสุดท้าย ดังนั้น การย้ายค่ายควรจะย้ายในสัปดาห์สุดท้ายของรอบเดือนเพื่อประโยชน์สูงสุดของเราเอง และเผื่อเวลาด้วยนะครับ ไม่ให้พลาด :) + +## What else? + +* เมื่อการย้ายค่ายเริ่มต้น จะมี SMS จากค่ายใหม่ส่งมาบอกว่าได้เริ่มต้นแล้ว และ SMS จากค่ายเดิมเพื่อเปลี่ยนใจไม่ให้ย้าย โดยได้โทรฟรี เล่นเน็ตฟรีซักช่วงนึงด้วย +* ระหว่างการย้ายค่ายจะมีช่วงที่ไม่สามารถใช้งานได้อยู่ประมาณ 24 ชม. สำหรับกรณีของผมเป็นทาง True ที่ปิดสัญญาณของ SIM เดิมประมาณตี 3 ของวันที่ 2 แล้ว DTAC สามารถใช้ได้เวลาประมาณตี 2 ของวันที่ 3 (โดยผมปิดๆเปิดๆเครื่องที่ใส่ SIM ใหม่ไว้ทุกๆ 2-3 ชม. ดังนั้นเวลาอาจจะคลาดเคลื่อนบ้างแต่คงไม่มากนัก) + +หวังว่าข้อมูลนี้จะช่วยให้คุณย้ายค่ายได้อย่างราบรื่นกว่าไม่รู้อะไรเลยครับ :) diff --git a/content/blog/2015-03-30-วัดบัวขวัญ-คุณห้ามหลง.md b/content/blog/2015-03-30-วัดบัวขวัญ-คุณห้ามหลง.md new file mode 100644 index 0000000..4d24b9b --- /dev/null +++ b/content/blog/2015-03-30-วัดบัวขวัญ-คุณห้ามหลง.md @@ -0,0 +1,18 @@ +title: คุณไม่รู้ทาง? เรามีทางแก้ไขจากวัดบัวขวัญ +date: Mar 30, 2015 +author: sipp11 +category: social +tags: failed +icon: briefcase +slug: คุณไม่รู้ทาง-เรามีทางแก้-จากวัดบัวขวัญ + + +ทุกคนก็น่าจะรู้ว่า ป้ายบอกทาง กับ เมืองไทยนั้นเป็นของที่น่าสับสนไม่ใช่น้อย ไม่ว่าจะวางตำแหน่งไม่ดี ไกลไป ใกล้ไป หรือ อีกอย่างก็คือ ถนนบ้านเรามันออกแบบอย่างไม่เป็นระบบมากพอที่จะทำให้ป้ายสามารถครอบคลุมได้ทุกสิ่ง + +แต่มันก็ไม่ทำให้วัด วัดหนึ่งยอมแพ้ต่อความยากลำบากนั้น วัดบัวขวัญนั้นแก้ไขด้วยการวางป้ายมันซะทุกที่ซะเลย ไม่ต้องห่วงว่าจะหลง เพราะถึงจะเลยทางเลี้ยงแล้ว ก็ยังมีป้ายแสดงให้กลับรถอีกด้วยนะครับ เรียกว่า บอกย้ำเส้นทางกันมากกว่า Nagivator ทั้งหลายพูดซะอีก + +![ป้ายแสดงทางไปวัดบัวขวัญ](/media/2015/03/bua-khwan-sign.png) + +ผมก็คงใส่เข้าไปเรื่อยๆนั่นแหละครับ นี่แค่ถ่ายเล่นๆ เวลาขับผ่านก็นับได้เกิน 30 ป้ายแล้ว ไม่รุ้ว่า วิธีการนี้จะได้ผลมั้ย แต่ที่แน่ๆ มันทำให้รู้ว่า เมืองไทยไม่มีระเบียบบ้าอะไรเลยจริงๆ :-/ + +ใครอยากเข้าไปดูรูปชัดๆ ว่า จริง หรือไม่จริง ก็เข้าไปได้ตามนี้ [Maps on Flickr](https://www.flickr.com/photos/37507575@N04/sets/72157651643441441/map?&fLat=13.8559&fLon=100.5115&zl=13&order_by=recent) ต้องของคุณ Flickr จริงๆ สำหรับพื้นที่ให้ upload รูปเยอะแยะ แถมจัดการสะดวกๆ :) \ No newline at end of file diff --git a/content/media/2015/03/bua-khwan-sign.png b/content/media/2015/03/bua-khwan-sign.png new file mode 100644 index 0000000..8a33863 Binary files /dev/null and b/content/media/2015/03/bua-khwan-sign.png differ diff --git a/content/media/2015/03/svg-edit-2.7/browser-not-supported.html b/content/media/2015/03/svg-edit-2.7/browser-not-supported.html new file mode 100755 index 0000000..efacce1 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/browser-not-supported.html @@ -0,0 +1,31 @@ + + + + + + + + +Browser does not support SVG | SVG-edit + + + +
+SVG-edit logo
+

Sorry, but your browser does not support SVG. Below is a list of alternate browsers and versions that support SVG and SVG-edit (from caniuse.com).

+

Try the latest version of Firefox, Google Chrome, Safari, Opera or Internet Explorer.

+

If you are unable to install one of these and must use an old version of Internet Explorer, you can install the Google Chrome Frame plugin.

+ +
+ + + + diff --git a/content/media/2015/03/svg-edit-2.7/browser.js b/content/media/2015/03/svg-edit-2.7/browser.js new file mode 100755 index 0000000..dc6ee6e --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/browser.js @@ -0,0 +1,180 @@ +/*globals $, svgedit*/ +/*jslint vars: true, eqeq: true*/ +/** + * Package: svgedit.browser + * + * Licensed under the MIT License + * + * Copyright(c) 2010 Jeff Schiller + * Copyright(c) 2010 Alexis Deveria + */ + +// Dependencies: +// 1) jQuery (for $.alert()) + +(function() {'use strict'; + +if (!svgedit.browser) { + svgedit.browser = {}; +} + +// alias +var NS = svgedit.NS; + +var supportsSvg_ = (function() { + return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect; +}()); + +svgedit.browser.supportsSvg = function() { return supportsSvg_; }; +if(!svgedit.browser.supportsSvg()) { + window.location = 'browser-not-supported.html'; + return; +} + +var userAgent = navigator.userAgent; +var svg = document.createElementNS(NS.SVG, 'svg'); + +// Note: Browser sniffing should only be used if no other detection method is possible +var isOpera_ = !!window.opera; +var isWebkit_ = userAgent.indexOf('AppleWebKit') >= 0; +var isGecko_ = userAgent.indexOf('Gecko/') >= 0; +var isIE_ = userAgent.indexOf('MSIE') >= 0; +var isChrome_ = userAgent.indexOf('Chrome/') >= 0; +var isWindows_ = userAgent.indexOf('Windows') >= 0; +var isMac_ = userAgent.indexOf('Macintosh') >= 0; +var isTouch_ = 'ontouchstart' in window; + +var supportsSelectors_ = (function() { + return !!svg.querySelector; +}()); + +var supportsXpath_ = (function() { + return !!document.evaluate; +}()); + +// segList functions (for FF1.5 and 2.0) +var supportsPathReplaceItem_ = (function() { + var path = document.createElementNS(NS.SVG, 'path'); + path.setAttribute('d', 'M0,0 10,10'); + var seglist = path.pathSegList; + var seg = path.createSVGPathSegLinetoAbs(5,5); + try { + seglist.replaceItem(seg, 0); + return true; + } catch(err) {} + return false; +}()); + +var supportsPathInsertItemBefore_ = (function() { + var path = document.createElementNS(NS.SVG, 'path'); + path.setAttribute('d', 'M0,0 10,10'); + var seglist = path.pathSegList; + var seg = path.createSVGPathSegLinetoAbs(5,5); + try { + seglist.insertItemBefore(seg, 0); + return true; + } catch(err) {} + return false; +}()); + +// text character positioning (for IE9) +var supportsGoodTextCharPos_ = (function() { + var svgroot = document.createElementNS(NS.SVG, 'svg'); + var svgcontent = document.createElementNS(NS.SVG, 'svg'); + document.documentElement.appendChild(svgroot); + svgcontent.setAttribute('x', 5); + svgroot.appendChild(svgcontent); + var text = document.createElementNS(NS.SVG, 'text'); + text.textContent = 'a'; + svgcontent.appendChild(text); + var pos = text.getStartPositionOfChar(0).x; + document.documentElement.removeChild(svgroot); + return (pos === 0); +}()); + +var supportsPathBBox_ = (function() { + var svgcontent = document.createElementNS(NS.SVG, 'svg'); + document.documentElement.appendChild(svgcontent); + var path = document.createElementNS(NS.SVG, 'path'); + path.setAttribute('d', 'M0,0 C0,0 10,10 10,0'); + svgcontent.appendChild(path); + var bbox = path.getBBox(); + document.documentElement.removeChild(svgcontent); + return (bbox.height > 4 && bbox.height < 5); +}()); + +// Support for correct bbox sizing on groups with horizontal/vertical lines +var supportsHVLineContainerBBox_ = (function() { + var svgcontent = document.createElementNS(NS.SVG, 'svg'); + document.documentElement.appendChild(svgcontent); + var path = document.createElementNS(NS.SVG, 'path'); + path.setAttribute('d', 'M0,0 10,0'); + var path2 = document.createElementNS(NS.SVG, 'path'); + path2.setAttribute('d', 'M5,0 15,0'); + var g = document.createElementNS(NS.SVG, 'g'); + g.appendChild(path); + g.appendChild(path2); + svgcontent.appendChild(g); + var bbox = g.getBBox(); + document.documentElement.removeChild(svgcontent); + // Webkit gives 0, FF gives 10, Opera (correctly) gives 15 + return (bbox.width == 15); +}()); + +var supportsEditableText_ = (function() { + // TODO: Find better way to check support for this + return isOpera_; +}()); + +var supportsGoodDecimals_ = (function() { + // Correct decimals on clone attributes (Opera < 10.5/win/non-en) + var rect = document.createElementNS(NS.SVG, 'rect'); + rect.setAttribute('x', 0.1); + var crect = rect.cloneNode(false); + var retValue = (crect.getAttribute('x').indexOf(',') == -1); + if(!retValue) { + $.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n'+ + 'Please upgrade to the latest version in which the problems have been fixed.'); + } + return retValue; +}()); + +var supportsNonScalingStroke_ = (function() { + var rect = document.createElementNS(NS.SVG, 'rect'); + rect.setAttribute('style', 'vector-effect:non-scaling-stroke'); + return rect.style.vectorEffect === 'non-scaling-stroke'; +}()); + +var supportsNativeSVGTransformLists_ = (function() { + var rect = document.createElementNS(NS.SVG, 'rect'); + var rxform = rect.transform.baseVal; + var t1 = svg.createSVGTransform(); + rxform.appendItem(t1); + return rxform.getItem(0) == t1; +}()); + +// Public API + +svgedit.browser.isOpera = function() { return isOpera_; }; +svgedit.browser.isWebkit = function() { return isWebkit_; }; +svgedit.browser.isGecko = function() { return isGecko_; }; +svgedit.browser.isIE = function() { return isIE_; }; +svgedit.browser.isChrome = function() { return isChrome_; }; +svgedit.browser.isWindows = function() { return isWindows_; }; +svgedit.browser.isMac = function() { return isMac_; }; +svgedit.browser.isTouch = function() { return isTouch_; }; + +svgedit.browser.supportsSelectors = function() { return supportsSelectors_; }; +svgedit.browser.supportsXpath = function() { return supportsXpath_; }; + +svgedit.browser.supportsPathReplaceItem = function() { return supportsPathReplaceItem_; }; +svgedit.browser.supportsPathInsertItemBefore = function() { return supportsPathInsertItemBefore_; }; +svgedit.browser.supportsPathBBox = function() { return supportsPathBBox_; }; +svgedit.browser.supportsHVLineContainerBBox = function() { return supportsHVLineContainerBBox_; }; +svgedit.browser.supportsGoodTextCharPos = function() { return supportsGoodTextCharPos_; }; +svgedit.browser.supportsEditableText = function() { return supportsEditableText_; }; +svgedit.browser.supportsGoodDecimals = function() { return supportsGoodDecimals_; }; +svgedit.browser.supportsNonScalingStroke = function() { return supportsNonScalingStroke_; }; +svgedit.browser.supportsNativeTransformLists = function() { return supportsNativeSVGTransformLists_; }; + +}()); diff --git a/content/media/2015/03/svg-edit-2.7/canvg/canvg.js b/content/media/2015/03/svg-edit-2.7/canvg/canvg.js new file mode 100755 index 0000000..87bf2b9 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/canvg/canvg.js @@ -0,0 +1,2620 @@ +/* + * canvg.js - Javascript SVG parser and renderer on Canvas + * MIT Licensed + * Gabe Lerner (gabelerner@gmail.com) + * http://code.google.com/p/canvg/ + * + * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/ + */ +if(!window.console) { + window.console = {}; + window.console.log = function(str) {}; + window.console.dir = function(str) {}; +} + +if(!Array.prototype.indexOf){ + Array.prototype.indexOf = function(obj){ + for(var i=0; i ignore mouse events + // ignoreAnimation: true => ignore animations + // ignoreDimensions: true => does not try to resize canvas + // ignoreClear: true => does not clear canvas + // offsetX: int => draws at a x offset + // offsetY: int => draws at a y offset + // scaleWidth: int => scales horizontally to width + // scaleHeight: int => scales vertically to height + // renderCallback: function => will call the function after the first render is completed + // forceRedraw: function => will call the function on every frame, if it returns true, will redraw + this.canvg = function (target, s, opts) { + // no parameters + if (target == null && s == null && opts == null) { + var svgTags = document.getElementsByTagName('svg'); + for (var i=0; i]*>/, ''); + var xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); + xmlDoc.async = 'false'; + xmlDoc.loadXML(xml); + return xmlDoc; + } + } + + svg.Property = function(name, value) { + this.name = name; + this.value = value; + + this.hasValue = function() { + return (this.value != null && this.value !== ''); + } + + // return the numerical value of the property + this.numValue = function() { + if (!this.hasValue()) return 0; + + var n = parseFloat(this.value); + if ((this.value + '').match(/%$/)) { + n = n / 100.0; + } + return n; + } + + this.valueOrDefault = function(def) { + if (this.hasValue()) return this.value; + return def; + } + + this.numValueOrDefault = function(def) { + if (this.hasValue()) return this.numValue(); + return def; + } + + /* EXTENSIONS */ + var that = this; + + // color extensions + this.Color = { + // augment the current color value with the opacity + addOpacity: function(opacity) { + var newValue = that.value; + if (opacity != null && opacity != '') { + var color = new RGBColor(that.value); + if (color.ok) { + newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacity + ')'; + } + } + return new svg.Property(that.name, newValue); + } + } + + // definition extensions + this.Definition = { + // get the definition from the definitions table + getDefinition: function() { + var name = that.value.replace(/^(url\()?#([^\)]+)\)?$/, '$2'); + return svg.Definitions[name]; + }, + + isUrl: function() { + return that.value.indexOf('url(') == 0 + }, + + getFillStyle: function(e) { + var def = this.getDefinition(); + + // gradient + if (def != null && def.createGradient) { + return def.createGradient(svg.ctx, e); + } + + // pattern + if (def != null && def.createPattern) { + return def.createPattern(svg.ctx, e); + } + + return null; + } + } + + // length extensions + this.Length = { + DPI: function(viewPort) { + return 96.0; // TODO: compute? + }, + + EM: function(viewPort) { + var em = 12; + + var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize); + if (fontSize.hasValue()) em = fontSize.Length.toPixels(viewPort); + + return em; + }, + + // get the length as pixels + toPixels: function(viewPort) { + if (!that.hasValue()) return 0; + var s = that.value+''; + if (s.match(/em$/)) return that.numValue() * this.EM(viewPort); + if (s.match(/ex$/)) return that.numValue() * this.EM(viewPort) / 2.0; + if (s.match(/px$/)) return that.numValue(); + if (s.match(/pt$/)) return that.numValue() * 1.25; + if (s.match(/pc$/)) return that.numValue() * 15; + if (s.match(/cm$/)) return that.numValue() * this.DPI(viewPort) / 2.54; + if (s.match(/mm$/)) return that.numValue() * this.DPI(viewPort) / 25.4; + if (s.match(/in$/)) return that.numValue() * this.DPI(viewPort); + if (s.match(/%$/)) return that.numValue() * svg.ViewPort.ComputeSize(viewPort); + return that.numValue(); + } + } + + // time extensions + this.Time = { + // get the time as milliseconds + toMilliseconds: function() { + if (!that.hasValue()) return 0; + var s = that.value+''; + if (s.match(/s$/)) return that.numValue() * 1000; + if (s.match(/ms$/)) return that.numValue(); + return that.numValue(); + } + } + + // angle extensions + this.Angle = { + // get the angle as radians + toRadians: function() { + if (!that.hasValue()) return 0; + var s = that.value+''; + if (s.match(/deg$/)) return that.numValue() * (Math.PI / 180.0); + if (s.match(/grad$/)) return that.numValue() * (Math.PI / 200.0); + if (s.match(/rad$/)) return that.numValue(); + return that.numValue() * (Math.PI / 180.0); + } + } + } + + // fonts + svg.Font = new (function() { + this.Styles = ['normal','italic','oblique','inherit']; + this.Variants = ['normal','small-caps','inherit']; + this.Weights = ['normal','bold','bolder','lighter','100','200','300','400','500','600','700','800','900','inherit']; + + this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) { + var f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font); + return { + fontFamily: fontFamily || f.fontFamily, + fontSize: fontSize || f.fontSize, + fontStyle: fontStyle || f.fontStyle, + fontWeight: fontWeight || f.fontWeight, + fontVariant: fontVariant || f.fontVariant, + toString: function () { return [this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(' ') } + } + } + + var that = this; + this.Parse = function(s) { + var f = {}; + var d = svg.trim(svg.compressSpaces(s || '')).split(' '); + var set = { fontSize: false, fontStyle: false, fontWeight: false, fontVariant: false } + var ff = ''; + for (var i=0; i this.x2) this.x2 = x; + } + + if (y != null) { + if (isNaN(this.y1) || isNaN(this.y2)) { + this.y1 = y; + this.y2 = y; + } + if (y < this.y1) this.y1 = y; + if (y > this.y2) this.y2 = y; + } + } + this.addX = function(x) { this.addPoint(x, null); } + this.addY = function(y) { this.addPoint(null, y); } + + this.addBoundingBox = function(bb) { + this.addPoint(bb.x1, bb.y1); + this.addPoint(bb.x2, bb.y2); + } + + this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) { + var cp1x = p0x + 2/3 * (p1x - p0x); // CP1 = QP0 + 2/3 *(QP1-QP0) + var cp1y = p0y + 2/3 * (p1y - p0y); // CP1 = QP0 + 2/3 *(QP1-QP0) + var cp2x = cp1x + 1/3 * (p2x - p0x); // CP2 = CP1 + 1/3 *(QP2-QP0) + var cp2y = cp1y + 1/3 * (p2y - p0y); // CP2 = CP1 + 1/3 *(QP2-QP0) + this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y); + } + + this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) { + // from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html + var p0 = [p0x, p0y], p1 = [p1x, p1y], p2 = [p2x, p2y], p3 = [p3x, p3y]; + this.addPoint(p0[0], p0[1]); + this.addPoint(p3[0], p3[1]); + + for (i=0; i<=1; i++) { + var f = function(t) { + return Math.pow(1-t, 3) * p0[i] + + 3 * Math.pow(1-t, 2) * t * p1[i] + + 3 * (1-t) * Math.pow(t, 2) * p2[i] + + Math.pow(t, 3) * p3[i]; + } + + var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i]; + var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i]; + var c = 3 * p1[i] - 3 * p0[i]; + + if (a == 0) { + if (b == 0) continue; + var t = -c / b; + if (0 < t && t < 1) { + if (i == 0) this.addX(f(t)); + if (i == 1) this.addY(f(t)); + } + continue; + } + + var b2ac = Math.pow(b, 2) - 4 * c * a; + if (b2ac < 0) continue; + var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); + if (0 < t1 && t1 < 1) { + if (i == 0) this.addX(f(t1)); + if (i == 1) this.addY(f(t1)); + } + var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); + if (0 < t2 && t2 < 1) { + if (i == 0) this.addX(f(t2)); + if (i == 1) this.addY(f(t2)); + } + } + } + + this.isPointInBox = function(x, y) { + return (this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2); + } + + this.addPoint(x1, y1); + this.addPoint(x2, y2); + } + + // transforms + svg.Transform = function(v) { + var that = this; + this.Type = {} + + // translate + this.Type.translate = function(s) { + this.p = svg.CreatePoint(s); + this.apply = function(ctx) { + ctx.translate(this.p.x || 0.0, this.p.y || 0.0); + } + this.applyToPoint = function(p) { + p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]); + } + } + + // rotate + this.Type.rotate = function(s) { + var a = svg.ToNumberArray(s); + this.angle = new svg.Property('angle', a[0]); + this.cx = a[1] || 0; + this.cy = a[2] || 0; + this.apply = function(ctx) { + ctx.translate(this.cx, this.cy); + ctx.rotate(this.angle.Angle.toRadians()); + ctx.translate(-this.cx, -this.cy); + } + this.applyToPoint = function(p) { + var a = this.angle.Angle.toRadians(); + p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]); + p.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]); + p.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]); + } + } + + this.Type.scale = function(s) { + this.p = svg.CreatePoint(s); + this.apply = function(ctx) { + ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0); + } + this.applyToPoint = function(p) { + p.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]); + } + } + + this.Type.matrix = function(s) { + this.m = svg.ToNumberArray(s); + this.apply = function(ctx) { + ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]); + } + this.applyToPoint = function(p) { + p.applyTransform(this.m); + } + } + + this.Type.SkewBase = function(s) { + this.base = that.Type.matrix; + this.base(s); + this.angle = new svg.Property('angle', s); + } + this.Type.SkewBase.prototype = new this.Type.matrix; + + this.Type.skewX = function(s) { + this.base = that.Type.SkewBase; + this.base(s); + this.m = [1, 0, Math.tan(this.angle.Angle.toRadians()), 1, 0, 0]; + } + this.Type.skewX.prototype = new this.Type.SkewBase; + + this.Type.skewY = function(s) { + this.base = that.Type.SkewBase; + this.base(s); + this.m = [1, Math.tan(this.angle.Angle.toRadians()), 0, 1, 0, 0]; + } + this.Type.skewY.prototype = new this.Type.SkewBase; + + this.transforms = []; + + this.apply = function(ctx) { + for (var i=0; i= this.tokens.length - 1; + } + + this.isCommandOrEnd = function() { + if (this.isEnd()) return true; + return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null; + } + + this.isRelativeCommand = function() { + return this.command == this.command.toLowerCase(); + } + + this.getToken = function() { + this.i = this.i + 1; + return this.tokens[this.i]; + } + + this.getScalar = function() { + return parseFloat(this.getToken()); + } + + this.nextCommand = function() { + this.previousCommand = this.command; + this.command = this.getToken(); + } + + this.getPoint = function() { + var p = new svg.Point(this.getScalar(), this.getScalar()); + return this.makeAbsolute(p); + } + + this.getAsControlPoint = function() { + var p = this.getPoint(); + this.control = p; + return p; + } + + this.getAsCurrentPoint = function() { + var p = this.getPoint(); + this.current = p; + return p; + } + + this.getReflectedControlPoint = function() { + if (this.previousCommand.toLowerCase() != 'c' && this.previousCommand.toLowerCase() != 's') { + return this.current; + } + + // reflect point + var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y); + return p; + } + + this.makeAbsolute = function(p) { + if (this.isRelativeCommand()) { + p.x = this.current.x + p.x; + p.y = this.current.y + p.y; + } + return p; + } + + this.addMarker = function(p, from, priorTo) { + // if the last angle isn't filled in because we didn't have this point yet ... + if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length-1] == null) { + this.angles[this.angles.length-1] = this.points[this.points.length-1].angleTo(priorTo); + } + this.addMarkerAngle(p, from == null ? null : from.angleTo(p)); + } + + this.addMarkerAngle = function(p, a) { + this.points.push(p); + this.angles.push(a); + } + + this.getMarkerPoints = function() { return this.points; } + this.getMarkerAngles = function() { + for (var i=0; i 1) { + rx *= Math.sqrt(l); + ry *= Math.sqrt(l); + } + // cx', cy' + var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt( + ((Math.pow(rx,2)*Math.pow(ry,2))-(Math.pow(rx,2)*Math.pow(currp.y,2))-(Math.pow(ry,2)*Math.pow(currp.x,2))) / + (Math.pow(rx,2)*Math.pow(currp.y,2)+Math.pow(ry,2)*Math.pow(currp.x,2)) + ); + if (isNaN(s)) s = 0; + var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx); + // cx, cy + var centp = new svg.Point( + (curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y, + (curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y + ); + // vector magnitude + var m = function(v) { return Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2)); } + // ratio between two vectors + var r = function(u, v) { return (u[0]*v[0]+u[1]*v[1]) / (m(u)*m(v)) } + // angle between two vectors + var a = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(r(u,v)); } + // initial angle + var a1 = a([1,0], [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]); + // angle delta + var u = [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]; + var v = [(-currp.x-cpp.x)/rx,(-currp.y-cpp.y)/ry]; + var ad = a(u, v); + if (r(u,v) <= -1) ad = Math.PI; + if (r(u,v) >= 1) ad = 0; + + if (sweepFlag == 0 && ad > 0) ad = ad - 2 * Math.PI; + if (sweepFlag == 1 && ad < 0) ad = ad + 2 * Math.PI; + + // for markers + var halfWay = new svg.Point( + centp.x - rx * Math.cos((a1 + ad) / 2), + centp.y - ry * Math.sin((a1 + ad) / 2) + ); + pp.addMarkerAngle(halfWay, (a1 + ad) / 2 + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2); + pp.addMarkerAngle(cp, ad + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2); + + bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better + if (ctx != null) { + var r = rx > ry ? rx : ry; + var sx = rx > ry ? 1 : rx / ry; + var sy = rx > ry ? ry / rx : 1; + + ctx.translate(centp.x, centp.y); + ctx.rotate(xAxisRotation); + ctx.scale(sx, sy); + ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag); + ctx.scale(1/sx, 1/sy); + ctx.rotate(-xAxisRotation); + ctx.translate(-centp.x, -centp.y); + } + } + break; + case 'Z': + if (ctx != null) ctx.closePath(); + pp.current = pp.start; + } + } + + return bb; + } + + this.getMarkers = function() { + var points = this.PathParser.getMarkerPoints(); + var angles = this.PathParser.getMarkerAngles(); + + var markers = []; + for (var i=0; i this.maxDuration) { + // loop for indefinitely repeating animations + if (this.attribute('repeatCount').value == 'indefinite') { + this.duration = 0.0 + } + else if (this.attribute('fill').valueOrDefault('remove') == 'remove' && !this.removed) { + this.removed = true; + this.getProperty().value = this.initialValue; + return true; + } + else { + return false; // no updates made + } + } + this.duration = this.duration + delta; + + // if we're past the begin time + var updated = false; + if (this.begin < this.duration) { + var newValue = this.calcValue(); // tween + + if (this.attribute('type').hasValue()) { + // for transform, etc. + var type = this.attribute('type').value; + newValue = type + '(' + newValue + ')'; + } + + this.getProperty().value = newValue; + updated = true; + } + + return updated; + } + + // fraction of duration we've covered + this.progress = function() { + return ((this.duration - this.begin) / (this.maxDuration - this.begin)); + } + } + svg.Element.AnimateBase.prototype = new svg.Element.ElementBase; + + // animate element + svg.Element.animate = function(node) { + this.base = svg.Element.AnimateBase; + this.base(node); + + this.calcValue = function() { + var from = this.attribute('from').numValue(); + var to = this.attribute('to').numValue(); + + // tween value linearly + return from + (to - from) * this.progress(); + }; + } + svg.Element.animate.prototype = new svg.Element.AnimateBase; + + // animate color element + svg.Element.animateColor = function(node) { + this.base = svg.Element.AnimateBase; + this.base(node); + + this.calcValue = function() { + var from = new RGBColor(this.attribute('from').value); + var to = new RGBColor(this.attribute('to').value); + + if (from.ok && to.ok) { + // tween color linearly + var r = from.r + (to.r - from.r) * this.progress(); + var g = from.g + (to.g - from.g) * this.progress(); + var b = from.b + (to.b - from.b) * this.progress(); + return 'rgb('+parseInt(r,10)+','+parseInt(g,10)+','+parseInt(b,10)+')'; + } + return this.attribute('from').value; + }; + } + svg.Element.animateColor.prototype = new svg.Element.AnimateBase; + + // animate transform element + svg.Element.animateTransform = function(node) { + this.base = svg.Element.animate; + this.base(node); + } + svg.Element.animateTransform.prototype = new svg.Element.animate; + + // font element + svg.Element.font = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.horizAdvX = this.attribute('horiz-adv-x').numValue(); + + this.isRTL = false; + this.isArabic = false; + this.fontFace = null; + this.missingGlyph = null; + this.glyphs = []; + for (var i=0; i0 && text[i-1]!=' ' && i0 && text[i-1]!=' ' && (i == text.length-1 || text[i+1]==' ')) arabicForm = 'initial'; + if (typeof(font.glyphs[c]) != 'undefined') { + glyph = font.glyphs[c][arabicForm]; + if (glyph == null && font.glyphs[c].type == 'glyph') glyph = font.glyphs[c]; + } + } + else { + glyph = font.glyphs[c]; + } + if (glyph == null) glyph = font.missingGlyph; + return glyph; + } + + this.renderChildren = function(ctx) { + var customFont = this.parent.style('font-family').Definition.getDefinition(); + if (customFont != null) { + var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize); + var fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle); + var text = this.getText(); + if (customFont.isRTL) text = text.split("").reverse().join(""); + + var dx = svg.ToNumberArray(this.parent.attribute('dx').value); + for (var i=0; i 0 ? node.childNodes[0].nodeValue : // element + node.text; + this.getText = function() { + return this.text; + } + } + svg.Element.tspan.prototype = new svg.Element.TextElementBase; + + // tref + svg.Element.tref = function(node) { + this.base = svg.Element.TextElementBase; + this.base(node); + + this.getText = function() { + var element = this.attribute('xlink:href').Definition.getDefinition(); + if (element != null) return element.children[0].getText(); + } + } + svg.Element.tref.prototype = new svg.Element.TextElementBase; + + // a element + svg.Element.a = function(node) { + this.base = svg.Element.TextElementBase; + this.base(node); + + this.hasText = true; + for (var i=0; i 1 ? node.childNodes[1].nodeValue : ''); + css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm, ''); // remove comments + css = svg.compressSpaces(css); // replace whitespace + var cssDefs = css.split('}'); + for (var i=0; i 0) { + var urlStart = srcs[s].indexOf('url'); + var urlEnd = srcs[s].indexOf(')', urlStart); + var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6); + var doc = svg.parseXml(svg.ajax(url)); + var fonts = doc.getElementsByTagName('font'); + for (var f=0; f + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ +function RGBColor(color_string) { 'use strict'; + this.ok = false; + + // strip any leading # + if (color_string.charAt(0) === '#') { // remove # if any + color_string = color_string.substr(1,6); + } + + color_string = color_string.replace(/ /g,''); + color_string = color_string.toLowerCase(); + + // before getting into regexps, try simple matches + // and overwrite the input + var simple_colors = { + aliceblue: 'f0f8ff', + antiquewhite: 'faebd7', + aqua: '00ffff', + aquamarine: '7fffd4', + azure: 'f0ffff', + beige: 'f5f5dc', + bisque: 'ffe4c4', + black: '000000', + blanchedalmond: 'ffebcd', + blue: '0000ff', + blueviolet: '8a2be2', + brown: 'a52a2a', + burlywood: 'deb887', + cadetblue: '5f9ea0', + chartreuse: '7fff00', + chocolate: 'd2691e', + coral: 'ff7f50', + cornflowerblue: '6495ed', + cornsilk: 'fff8dc', + crimson: 'dc143c', + cyan: '00ffff', + darkblue: '00008b', + darkcyan: '008b8b', + darkgoldenrod: 'b8860b', + darkgray: 'a9a9a9', + darkgreen: '006400', + darkkhaki: 'bdb76b', + darkmagenta: '8b008b', + darkolivegreen: '556b2f', + darkorange: 'ff8c00', + darkorchid: '9932cc', + darkred: '8b0000', + darksalmon: 'e9967a', + darkseagreen: '8fbc8f', + darkslateblue: '483d8b', + darkslategray: '2f4f4f', + darkturquoise: '00ced1', + darkviolet: '9400d3', + deeppink: 'ff1493', + deepskyblue: '00bfff', + dimgray: '696969', + dodgerblue: '1e90ff', + feldspar: 'd19275', + firebrick: 'b22222', + floralwhite: 'fffaf0', + forestgreen: '228b22', + fuchsia: 'ff00ff', + gainsboro: 'dcdcdc', + ghostwhite: 'f8f8ff', + gold: 'ffd700', + goldenrod: 'daa520', + gray: '808080', + green: '008000', + greenyellow: 'adff2f', + honeydew: 'f0fff0', + hotpink: 'ff69b4', + indianred : 'cd5c5c', + indigo : '4b0082', + ivory: 'fffff0', + khaki: 'f0e68c', + lavender: 'e6e6fa', + lavenderblush: 'fff0f5', + lawngreen: '7cfc00', + lemonchiffon: 'fffacd', + lightblue: 'add8e6', + lightcoral: 'f08080', + lightcyan: 'e0ffff', + lightgoldenrodyellow: 'fafad2', + lightgrey: 'd3d3d3', + lightgreen: '90ee90', + lightpink: 'ffb6c1', + lightsalmon: 'ffa07a', + lightseagreen: '20b2aa', + lightskyblue: '87cefa', + lightslateblue: '8470ff', + lightslategray: '778899', + lightsteelblue: 'b0c4de', + lightyellow: 'ffffe0', + lime: '00ff00', + limegreen: '32cd32', + linen: 'faf0e6', + magenta: 'ff00ff', + maroon: '800000', + mediumaquamarine: '66cdaa', + mediumblue: '0000cd', + mediumorchid: 'ba55d3', + mediumpurple: '9370d8', + mediumseagreen: '3cb371', + mediumslateblue: '7b68ee', + mediumspringgreen: '00fa9a', + mediumturquoise: '48d1cc', + mediumvioletred: 'c71585', + midnightblue: '191970', + mintcream: 'f5fffa', + mistyrose: 'ffe4e1', + moccasin: 'ffe4b5', + navajowhite: 'ffdead', + navy: '000080', + oldlace: 'fdf5e6', + olive: '808000', + olivedrab: '6b8e23', + orange: 'ffa500', + orangered: 'ff4500', + orchid: 'da70d6', + palegoldenrod: 'eee8aa', + palegreen: '98fb98', + paleturquoise: 'afeeee', + palevioletred: 'd87093', + papayawhip: 'ffefd5', + peachpuff: 'ffdab9', + peru: 'cd853f', + pink: 'ffc0cb', + plum: 'dda0dd', + powderblue: 'b0e0e6', + purple: '800080', + red: 'ff0000', + rosybrown: 'bc8f8f', + royalblue: '4169e1', + saddlebrown: '8b4513', + salmon: 'fa8072', + sandybrown: 'f4a460', + seagreen: '2e8b57', + seashell: 'fff5ee', + sienna: 'a0522d', + silver: 'c0c0c0', + skyblue: '87ceeb', + slateblue: '6a5acd', + slategray: '708090', + snow: 'fffafa', + springgreen: '00ff7f', + steelblue: '4682b4', + tan: 'd2b48c', + teal: '008080', + thistle: 'd8bfd8', + tomato: 'ff6347', + turquoise: '40e0d0', + violet: 'ee82ee', + violetred: 'd02090', + wheat: 'f5deb3', + white: 'ffffff', + whitesmoke: 'f5f5f5', + yellow: 'ffff00', + yellowgreen: '9acd32' + }; + var key; + for (key in simple_colors) { + if (simple_colors.hasOwnProperty(key)) { + if (color_string == key) { + color_string = simple_colors[key]; + } + } + } + // emd of simple type-in colors + + // array of color definition objects + var color_defs = [ + { + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], + process: function (bits){ + return [ + parseInt(bits[1], 10), + parseInt(bits[2], 10), + parseInt(bits[3], 10) + ]; + } + }, + { + re: /^(\w{2})(\w{2})(\w{2})$/, + example: ['#00ff00', '336699'], + process: function (bits){ + return [ + parseInt(bits[1], 16), + parseInt(bits[2], 16), + parseInt(bits[3], 16) + ]; + } + }, + { + re: /^(\w{1})(\w{1})(\w{1})$/, + example: ['#fb0', 'f0f'], + process: function (bits){ + return [ + parseInt(bits[1] + bits[1], 16), + parseInt(bits[2] + bits[2], 16), + parseInt(bits[3] + bits[3], 16) + ]; + } + } + ]; + + var i; + // search through the definitions to find a match + for (i = 0; i < color_defs.length; i++) { + var re = color_defs[i].re; + var processor = color_defs[i].process; + var bits = re.exec(color_string); + if (bits) { + var channels = processor(bits); + this.r = channels[0]; + this.g = channels[1]; + this.b = channels[2]; + this.ok = true; + } + + } + + // validate/cleanup values + this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); + this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); + this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b); + + // some getters + this.toRGB = function () { + return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; + }; + this.toHex = function () { + var r = this.r.toString(16); + var g = this.g.toString(16); + var b = this.b.toString(16); + if (r.length === 1) {r = '0' + r;} + if (g.length === 1) {g = '0' + g;} + if (b.length === 1) {b = '0' + b;} + return '#' + r + g + b; + }; + + // help + this.getHelpXML = function () { + var i, j; + var examples = []; + // add regexps + for (i = 0; i < color_defs.length; i++) { + var example = color_defs[i].example; + for (j = 0; j < example.length; j++) { + examples[examples.length] = example[j]; + } + } + // add type-in colors + var sc; + for (sc in simple_colors) { + if (simple_colors.hasOwnProperty(sc)) { + examples[examples.length] = sc; + } + } + + var xml = document.createElement('ul'); + xml.setAttribute('id', 'rgbcolor-examples'); + for (i = 0; i < examples.length; i++) { + try { + var list_item = document.createElement('li'); + var list_color = new RGBColor(examples[i]); + var example_div = document.createElement('div'); + example_div.style.cssText = + 'margin: 3px; ' + + 'border: 1px solid black; ' + + 'background:' + list_color.toHex() + '; ' + + 'color:' + list_color.toHex() + ; + example_div.appendChild(document.createTextNode('test')); + var list_item_value = document.createTextNode( + ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex() + ); + list_item.appendChild(example_div); + list_item.appendChild(list_item_value); + xml.appendChild(list_item); + + } catch(e){} + } + return xml; + + }; + +} diff --git a/content/media/2015/03/svg-edit-2.7/config-sample.js b/content/media/2015/03/svg-edit-2.7/config-sample.js new file mode 100755 index 0000000..fd93a22 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/config-sample.js @@ -0,0 +1,145 @@ +// DO NOT EDIT THIS FILE! +// THIS FILE IS JUST A SAMPLE; TO APPLY, YOU MUST +// CREATE A NEW FILE config.js AND ADD CONTENTS +// SUCH AS SHOWN BELOW INTO THAT FILE. + +/*globals svgEditor*/ +/* +The config.js file is intended for the setting of configuration or + preferences which must run early on; if this is not needed, it is + recommended that you create an extension instead (for greater + reusability and modularity). +*/ + +// CONFIG AND EXTENSION SETTING +/* +See defaultConfig and defaultExtensions in svg-editor.js for a list + of possible configuration settings. + +See svg-editor.js for documentation on using setConfig(). +*/ + +// URL OVERRIDE CONFIG +svgEditor.setConfig({ + /** + To override the ability for URLs to set URL-based SVG content, + uncomment the following: + */ + // preventURLContentLoading: true, + /** + To override the ability for URLs to set other configuration (including + extensions), uncomment the following: + */ + // preventAllURLConfig: true, + /** + To override the ability for URLs to set their own extensions, + uncomment the following (note that if setConfig() is used in + extension code, it will still be additive to extensions, + however): + */ + // lockExtensions: true, +}); + +svgEditor.setConfig({ + /* + Provide default values here which differ from that of the editor but + which the URL can override + */ +}, {allowInitialUserOverride: true}); + +// EXTENSION CONFIG +svgEditor.setConfig({ + extensions: [ + // 'ext-overview_window.js', 'ext-markers.js', 'ext-connector.js', 'ext-eyedropper.js', 'ext-shapes.js', 'ext-imagelib.js', 'ext-grid.js', 'ext-polygon.js', 'ext-star.js', 'ext-panning.js', 'ext-storage.js' + ] + // , noDefaultExtensions: false, // noDefaultExtensions can only be meaningfully used in config.js or in the URL +}); + +// OTHER CONFIG +svgEditor.setConfig({ + // canvasName: 'default', + // canvas_expansion: 3, + // initFill: { + // color: 'FF0000', // solid red + // opacity: 1 + // }, + // initStroke: { + // width: 5, + // color: '000000', // solid black + // opacity: 1 + // }, + // initOpacity: 1, + // colorPickerCSS: null, + // initTool: 'select', + // wireframe: false, + // showlayers: false, + // no_save_warning: false, + // PATH CONFIGURATION + // imgPath: 'images/', + // langPath: 'locale/', + // extPath: 'extensions/', + // jGraduatePath: 'jgraduate/images/', + /* + Uncomment the following to allow at least same domain (embedded) access, + including file:// access. + Setting as `['*']` would allow any domain to access but would be unsafe to + data privacy and integrity. + */ + // allowedOrigins: [window.location.origin || 'null'], // May be 'null' (as a string) when used as a file:// URL + // DOCUMENT PROPERTIES + // dimensions: [640, 480], + // EDITOR OPTIONS + // gridSnapping: false, + // gridColor: '#000', + // baseUnit: 'px', + // snappingStep: 10, + // showRulers: true, + // EXTENSION-RELATED (GRID) + // showGrid: false, // Set by ext-grid.js + // EXTENSION-RELATED (STORAGE) + // noStorageOnLoad: false, // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage + // forceStorage: false, // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not + // emptyStorageOnDecline: true, // Used by ext-storage.js; empty any prior storage if the user declines to store +}); + +// PREF CHANGES +/** +setConfig() can also be used to set preferences in addition to + configuration (see defaultPrefs in svg-editor.js for a list of + possible settings), but at least if you are using ext-storage.js + to store preferences, it will probably be better to let your + users control these. +As with configuration, one may use allowInitialUserOverride, but + in the case of preferences, any previously stored preferences + will also thereby be enabled to override this setting (and at a + higher priority than any URL preference setting overrides). + Failing to use allowInitialUserOverride will ensure preferences + are hard-coded here regardless of URL or prior user storage setting. +*/ +svgEditor.setConfig( + { + // lang: '', // Set dynamically within locale.js if not previously set + // iconsize: '', // Will default to 's' if the window height is smaller than the minimum height and 'm' otherwise + /** + * When showing the preferences dialog, svg-editor.js currently relies + * on curPrefs instead of $.pref, so allowing an override for bkgd_color + * means that this value won't have priority over block auto-detection as + * far as determining which color shows initially in the preferences + * dialog (though it can be changed and saved). + */ + // bkgd_color: '#FFF', + // bkgd_url: '', + // img_save: 'embed', + // Only shows in UI as far as alert notices + // save_notice_done: false, + // export_notice_done: false + } +); +svgEditor.setConfig( + { + // Indicate pref settings here if you wish to allow user storage or URL settings + // to be able to override your default preferences (unless other config options + // have already explicitly prevented one or the other) + }, + {allowInitialUserOverride: true} +); diff --git a/content/media/2015/03/svg-edit-2.7/config.js b/content/media/2015/03/svg-edit-2.7/config.js new file mode 100755 index 0000000..1364c44 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/config.js @@ -0,0 +1,12 @@ +/*globals svgEditor*/ + +svgEditor.setConfig({ +// extensions: [ +// 'ext-eyedropper.js', +// 'ext-shapes.js', +// 'ext-polygon.js', +// 'ext-star.js' +//], +//emptyStorageOnDecline: true + allowedOrigins: [window.location.origin] // May be 'null' (as a string) when used as a file:// URL +}); diff --git a/content/media/2015/03/svg-edit-2.7/contextmenu.js b/content/media/2015/03/svg-edit-2.7/contextmenu.js new file mode 100755 index 0000000..9fca31d --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/contextmenu.js @@ -0,0 +1,66 @@ +/*globals $, svgEditor*/ +/*jslint vars: true, eqeq: true*/ +/** + * Package: svgedit.contextmenu + * + * Licensed under the Apache License, Version 2 + * + * Author: Adam Bender + */ +// Dependencies: +// 1) jQuery (for dom injection of context menus) +var svgedit = svgedit || {}; +(function() { + var self = this; + if (!svgedit.contextmenu) { + svgedit.contextmenu = {}; + } + self.contextMenuExtensions = {}; + var menuItemIsValid = function(menuItem) { + return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action == 'function'; + }; + var addContextMenuItem = function(menuItem) { + // menuItem: {id, label, shortcut, action} + if (!menuItemIsValid(menuItem)) { + console.error("Menu items must be defined and have at least properties: id, label, action, where action must be a function"); + return; + } + if (menuItem.id in self.contextMenuExtensions) { + console.error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"'); + return; + } + // Register menuItem action, see below for deferred menu dom injection + console.log("Registed contextmenu item: {id:"+ menuItem.id+", label:"+menuItem.label+"}"); + self.contextMenuExtensions[menuItem.id] = menuItem; + //TODO: Need to consider how to handle custom enable/disable behavior + }; + var hasCustomHandler = function(handlerKey) { + return self.contextMenuExtensions[handlerKey] && true; + }; + var getCustomHandler = function(handlerKey) { + return self.contextMenuExtensions[handlerKey].action; + }; + var injectExtendedContextMenuItemIntoDom = function(menuItem) { + if (Object.keys(self.contextMenuExtensions).length === 0) { + // all menuItems appear at the bottom of the menu in their own container. + // if this is the first extension menu we need to add the separator. + $("#cmenu_canvas").append("
  • "); + } + var shortcut = menuItem.shortcut || ""; + $("#cmenu_canvas").append("
  • " + + menuItem.label + "" + + shortcut + "
  • "); + }; + // Defer injection to wait out initial menu processing. This probably goes away once all context + // menu behavior is brought here. + svgEditor.ready(function() { + var menuItem; + for (menuItem in contextMenuExtensions) { + injectExtendedContextMenuItemIntoDom(contextMenuExtensions[menuItem]); + } + }); + svgedit.contextmenu.resetCustomMenus = function(){self.contextMenuExtensions = {};}; + svgedit.contextmenu.add = addContextMenuItem; + svgedit.contextmenu.hasCustomHandler = hasCustomHandler; + svgedit.contextmenu.getCustomHandler = getCustomHandler; +}()); diff --git a/content/media/2015/03/svg-edit-2.7/contextmenu/jquery.contextMenu.js b/content/media/2015/03/svg-edit-2.7/contextmenu/jquery.contextMenu.js new file mode 100755 index 0000000..7612601 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/contextmenu/jquery.contextMenu.js @@ -0,0 +1,203 @@ +// jQuery Context Menu Plugin +// +// Version 1.01 +// +// Cory S.N. LaViska +// A Beautiful Site (http://abeautifulsite.net/) +// Modified by Alexis Deveria +// +// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/ +// +// Terms of Use +// +// This plugin is dual-licensed under the GNU General Public License +// and the MIT License and is copyright A Beautiful Site, LLC. +// +if(jQuery)( function() { + var win = $(window); + var doc = $(document); + + $.extend($.fn, { + + contextMenu: function(o, callback) { + // Defaults + if( o.menu == undefined ) return false; + if( o.inSpeed == undefined ) o.inSpeed = 150; + if( o.outSpeed == undefined ) o.outSpeed = 75; + // 0 needs to be -1 for expected results (no fade) + if( o.inSpeed == 0 ) o.inSpeed = -1; + if( o.outSpeed == 0 ) o.outSpeed = -1; + // Loop each context menu + $(this).each( function() { + var el = $(this); + var offset = $(el).offset(); + + var menu = $('#' + o.menu); + + // Add contextMenu class + menu.addClass('contextMenu'); + // Simulate a true right click + $(this).bind( "mousedown", function(e) { + var evt = e; + $(this).mouseup( function(e) { + var srcElement = $(this); + srcElement.unbind('mouseup'); + if( evt.button === 2 || o.allowLeft || (evt.ctrlKey && svgedit.browser.isMac()) ) { + e.stopPropagation(); + // Hide context menus that may be showing + $(".contextMenu").hide(); + // Get this context menu + + if( el.hasClass('disabled') ) return false; + + // Detect mouse position + var d = {}, x = e.pageX, y = e.pageY; + + var x_off = win.width() - menu.width(), + y_off = win.height() - menu.height(); + + if(x > x_off - 15) x = x_off-15; + if(y > y_off - 30) y = y_off-30; // 30 is needed to prevent scrollbars in FF + + // Show the menu + doc.unbind('click'); + menu.css({ top: y, left: x }).fadeIn(o.inSpeed); + // Hover events + menu.find('A').mouseover( function() { + menu.find('LI.hover').removeClass('hover'); + $(this).parent().addClass('hover'); + }).mouseout( function() { + menu.find('LI.hover').removeClass('hover'); + }); + + // Keyboard + doc.keypress( function(e) { + switch( e.keyCode ) { + case 38: // up + if( !menu.find('LI.hover').length ) { + menu.find('LI:last').addClass('hover'); + } else { + menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover'); + if( !menu.find('LI.hover').length ) menu.find('LI:last').addClass('hover'); + } + break; + case 40: // down + if( menu.find('LI.hover').length == 0 ) { + menu.find('LI:first').addClass('hover'); + } else { + menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover'); + if( !menu.find('LI.hover').length ) menu.find('LI:first').addClass('hover'); + } + break; + case 13: // enter + menu.find('LI.hover A').trigger('click'); + break; + case 27: // esc + doc.trigger('click'); + break + } + }); + + // When items are selected + menu.find('A').unbind('mouseup'); + menu.find('LI:not(.disabled) A').mouseup( function() { + doc.unbind('click').unbind('keypress'); + $(".contextMenu").hide(); + // Callback + if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} ); + return false; + }); + + // Hide bindings + setTimeout( function() { // Delay for Mozilla + doc.click( function() { + doc.unbind('click').unbind('keypress'); + menu.fadeOut(o.outSpeed); + return false; + }); + }, 0); + } + }); + }); + + // Disable text selection + if( $.browser.mozilla ) { + $('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); }); + } else if( $.browser.msie ) { + $('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); }); + } else { + $('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); }); + } + // Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome) + $(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; }); + + }); + return $(this); + }, + + // Disable context menu items on the fly + disableContextMenuItems: function(o) { + if( o == undefined ) { + // Disable all + $(this).find('LI').addClass('disabled'); + return( $(this) ); + } + $(this).each( function() { + if( o != undefined ) { + var d = o.split(','); + for( var i = 0; i < d.length; i++ ) { + $(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled'); + + } + } + }); + return( $(this) ); + }, + + // Enable context menu items on the fly + enableContextMenuItems: function(o) { + if( o == undefined ) { + // Enable all + $(this).find('LI.disabled').removeClass('disabled'); + return( $(this) ); + } + $(this).each( function() { + if( o != undefined ) { + var d = o.split(','); + for( var i = 0; i < d.length; i++ ) { + $(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled'); + + } + } + }); + return( $(this) ); + }, + + // Disable context menu(s) + disableContextMenu: function() { + $(this).each( function() { + $(this).addClass('disabled'); + }); + return( $(this) ); + }, + + // Enable context menu(s) + enableContextMenu: function() { + $(this).each( function() { + $(this).removeClass('disabled'); + }); + return( $(this) ); + }, + + // Destroy context menu(s) + destroyContextMenu: function() { + // Destroy specified context menus + $(this).each( function() { + // Disable action + $(this).unbind('mousedown').unbind('mouseup'); + }); + return( $(this) ); + } + + }); +})(jQuery); \ No newline at end of file diff --git a/content/media/2015/03/svg-edit-2.7/coords.js b/content/media/2015/03/svg-edit-2.7/coords.js new file mode 100755 index 0000000..7105aee --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/coords.js @@ -0,0 +1,316 @@ +/*globals $, svgroot */ +/*jslint vars: true, eqeq: true, forin: true*/ +/** + * Coords. + * + * Licensed under the MIT License + * + */ + +// Dependencies: +// 1) jquery.js +// 2) math.js +// 3) browser.js +// 4) svgutils.js +// 5) units.js +// 6) svgtransformlist.js + +var svgedit = svgedit || {}; + +(function() {'use strict'; + +if (!svgedit.coords) { + svgedit.coords = {}; +} + +// this is how we map paths to our preferred relative segment types +var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a', + 'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; + +/** + * @typedef editorContext + * @type {?object} + * @property {function} getGridSnapping + * @property {function} getDrawing +*/ +var editorContext_ = null; + +/** +* @param {editorContext} editorContext +*/ +svgedit.coords.init = function(editorContext) { + editorContext_ = editorContext; +}; + +/** + * Applies coordinate changes to an element based on the given matrix + * @param {Element} selected - DOM element to be changed + * @param {object} changes - Object with changes to be remapped + * @param {SVGMatrix} m - Matrix object to use for remapping coordinates +*/ +svgedit.coords.remapElement = function(selected, changes, m) { + var i, type, + remap = function(x, y) { return svgedit.math.transformPoint(x, y, m); }, + scalew = function(w) { return m.a * w; }, + scaleh = function(h) { return m.d * h; }, + doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg', + finishUp = function() { + var o; + if (doSnapping) { + for (o in changes) { + changes[o] = svgedit.utilities.snapToGrid(changes[o]); + } + } + svgedit.utilities.assignAttributes(selected, changes, 1000, true); + }, + box = svgedit.utilities.getBBox(selected); + + for (i = 0; i < 2; i++) { + type = i === 0 ? 'fill' : 'stroke'; + var attrVal = selected.getAttribute(type); + if (attrVal && attrVal.indexOf('url(') === 0) { + if (m.a < 0 || m.d < 0) { + var grad = svgedit.utilities.getRefElem(attrVal); + var newgrad = grad.cloneNode(true); + if (m.a < 0) { + // flip x + var x1 = newgrad.getAttribute('x1'); + var x2 = newgrad.getAttribute('x2'); + newgrad.setAttribute('x1', -(x1 - 1)); + newgrad.setAttribute('x2', -(x2 - 1)); + } + + if (m.d < 0) { + // flip y + var y1 = newgrad.getAttribute('y1'); + var y2 = newgrad.getAttribute('y2'); + newgrad.setAttribute('y1', -(y1 - 1)); + newgrad.setAttribute('y2', -(y2 - 1)); + } + newgrad.id = editorContext_.getDrawing().getNextId(); + svgedit.utilities.findDefs().appendChild(newgrad); + selected.setAttribute(type, 'url(#' + newgrad.id + ')'); + } + + // Not really working :( +// if (selected.tagName === 'path') { +// reorientGrads(selected, m); +// } + } + } + + var elName = selected.tagName; + var chlist, mt; + if (elName === 'g' || elName === 'text' || elName == 'tspan' || elName === 'use') { + // if it was a translate, then just update x,y + if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && (m.e != 0 || m.f != 0) ) { + // [T][M] = [M][T'] + // therefore [T'] = [M_inv][T][M] + var existing = svgedit.math.transformListToTransform(selected).matrix, + t_new = svgedit.math.matrixMultiply(existing.inverse(), m, existing); + changes.x = parseFloat(changes.x) + t_new.e; + changes.y = parseFloat(changes.y) + t_new.f; + } else { + // we just absorb all matrices into the element and don't do any remapping + chlist = svgedit.transformlist.getTransformList(selected); + mt = svgroot.createSVGTransform(); + mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m)); + chlist.clear(); + chlist.appendItem(mt); + } + } + var c, pt, pt1, pt2, len; + // now we have a set of changes and an applied reduced transform list + // we apply the changes directly to the DOM + switch (elName) { + case 'foreignObject': + case 'rect': + case 'image': + // Allow images to be inverted (give them matrix when flipped) + if (elName === 'image' && (m.a < 0 || m.d < 0)) { + // Convert to matrix + chlist = svgedit.transformlist.getTransformList(selected); + mt = svgroot.createSVGTransform(); + mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m)); + chlist.clear(); + chlist.appendItem(mt); + } else { + pt1 = remap(changes.x, changes.y); + changes.width = scalew(changes.width); + changes.height = scaleh(changes.height); + changes.x = pt1.x + Math.min(0, changes.width); + changes.y = pt1.y + Math.min(0, changes.height); + changes.width = Math.abs(changes.width); + changes.height = Math.abs(changes.height); + } + finishUp(); + break; + case 'ellipse': + c = remap(changes.cx, changes.cy); + changes.cx = c.x; + changes.cy = c.y; + changes.rx = scalew(changes.rx); + changes.ry = scaleh(changes.ry); + changes.rx = Math.abs(changes.rx); + changes.ry = Math.abs(changes.ry); + finishUp(); + break; + case 'circle': + c = remap(changes.cx,changes.cy); + changes.cx = c.x; + changes.cy = c.y; + // take the minimum of the new selected box's dimensions for the new circle radius + var tbox = svgedit.math.transformBox(box.x, box.y, box.width, box.height, m); + var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y; + changes.r = Math.min(w/2, h/2); + + if (changes.r) {changes.r = Math.abs(changes.r);} + finishUp(); + break; + case 'line': + pt1 = remap(changes.x1, changes.y1); + pt2 = remap(changes.x2, changes.y2); + changes.x1 = pt1.x; + changes.y1 = pt1.y; + changes.x2 = pt2.x; + changes.y2 = pt2.y; + // deliberately fall through here + case 'text': + case 'tspan': + case 'use': + finishUp(); + break; + case 'g': + var gsvg = $(selected).data('gsvg'); + if (gsvg) { + svgedit.utilities.assignAttributes(gsvg, changes, 1000, true); + } + break; + case 'polyline': + case 'polygon': + len = changes.points.length; + for (i = 0; i < len; ++i) { + pt = changes.points[i]; + pt = remap(pt.x, pt.y); + changes.points[i].x = pt.x; + changes.points[i].y = pt.y; + } + + len = changes.points.length; + var pstr = ''; + for (i = 0; i < len; ++i) { + pt = changes.points[i]; + pstr += pt.x + ',' + pt.y + ' '; + } + selected.setAttribute('points', pstr); + break; + case 'path': + var seg; + var segList = selected.pathSegList; + len = segList.numberOfItems; + changes.d = []; + for (i = 0; i < len; ++i) { + seg = segList.getItem(i); + changes.d[i] = { + type: seg.pathSegType, + x: seg.x, + y: seg.y, + x1: seg.x1, + y1: seg.y1, + x2: seg.x2, + y2: seg.y2, + r1: seg.r1, + r2: seg.r2, + angle: seg.angle, + largeArcFlag: seg.largeArcFlag, + sweepFlag: seg.sweepFlag + }; + } + + len = changes.d.length; + var firstseg = changes.d[0], + currentpt = remap(firstseg.x, firstseg.y); + changes.d[0].x = currentpt.x; + changes.d[0].y = currentpt.y; + for (i = 1; i < len; ++i) { + seg = changes.d[i]; + type = seg.type; + // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2 + // if relative, we want to scalew, scaleh + if (type % 2 == 0) { // absolute + var thisx = (seg.x != undefined) ? seg.x : currentpt.x, // for V commands + thisy = (seg.y != undefined) ? seg.y : currentpt.y; // for H commands + pt = remap(thisx,thisy); + pt1 = remap(seg.x1, seg.y1); + pt2 = remap(seg.x2, seg.y2); + seg.x = pt.x; + seg.y = pt.y; + seg.x1 = pt1.x; + seg.y1 = pt1.y; + seg.x2 = pt2.x; + seg.y2 = pt2.y; + seg.r1 = scalew(seg.r1); + seg.r2 = scaleh(seg.r2); + } + else { // relative + seg.x = scalew(seg.x); + seg.y = scaleh(seg.y); + seg.x1 = scalew(seg.x1); + seg.y1 = scaleh(seg.y1); + seg.x2 = scalew(seg.x2); + seg.y2 = scaleh(seg.y2); + seg.r1 = scalew(seg.r1); + seg.r2 = scaleh(seg.r2); + } + } // for each segment + + var dstr = ''; + len = changes.d.length; + for (i = 0; i < len; ++i) { + seg = changes.d[i]; + type = seg.type; + dstr += pathMap[type]; + switch (type) { + case 13: // relative horizontal line (h) + case 12: // absolute horizontal line (H) + dstr += seg.x + ' '; + break; + case 15: // relative vertical line (v) + case 14: // absolute vertical line (V) + dstr += seg.y + ' '; + break; + case 3: // relative move (m) + case 5: // relative line (l) + case 19: // relative smooth quad (t) + case 2: // absolute move (M) + case 4: // absolute line (L) + case 18: // absolute smooth quad (T) + dstr += seg.x + ',' + seg.y + ' '; + break; + case 7: // relative cubic (c) + case 6: // absolute cubic (C) + dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' + + seg.x + ',' + seg.y + ' '; + break; + case 9: // relative quad (q) + case 8: // absolute quad (Q) + dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' '; + break; + case 11: // relative elliptical arc (a) + case 10: // absolute elliptical arc (A) + dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + (+seg.largeArcFlag) + + ' ' + (+seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' '; + break; + case 17: // relative smooth cubic (s) + case 16: // absolute smooth cubic (S) + dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' '; + break; + } + } + + selected.setAttribute('d', dstr); + break; + } +}; + +}()); diff --git a/content/media/2015/03/svg-edit-2.7/draw.js b/content/media/2015/03/svg-edit-2.7/draw.js new file mode 100755 index 0000000..f79b803 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/draw.js @@ -0,0 +1,537 @@ +/*globals $, svgedit*/ +/*jslint vars: true, eqeq: true, todo: true*/ +/** + * Package: svgedit.draw + * + * Licensed under the MIT License + * + * Copyright(c) 2011 Jeff Schiller + */ + +// Dependencies: +// 1) jQuery +// 2) browser.js +// 3) svgutils.js + +(function() {'use strict'; + +if (!svgedit.draw) { + svgedit.draw = {}; +} +// alias +var NS = svgedit.NS; + +var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'.split(','); + +var RandomizeModes = { + LET_DOCUMENT_DECIDE: 0, + ALWAYS_RANDOMIZE: 1, + NEVER_RANDOMIZE: 2 +}; +var randomize_ids = RandomizeModes.LET_DOCUMENT_DECIDE; + +/** + * This class encapsulates the concept of a layer in the drawing + * @param {String} name - Layer name + * @param {SVGGElement} child - Layer SVG group. + */ +svgedit.draw.Layer = function(name, group) { + this.name_ = name; + this.group_ = group; +}; + +/** + * @returns {string} The layer name + */ +svgedit.draw.Layer.prototype.getName = function() { + return this.name_; +}; + +/** + * @returns {SVGGElement} The layer SVG group + */ +svgedit.draw.Layer.prototype.getGroup = function() { + return this.group_; +}; + + +/** + * Called to ensure that drawings will or will not have randomized ids. + * The currentDrawing will have its nonce set if it doesn't already. + * @param {boolean} enableRandomization - flag indicating if documents should have randomized ids + * @param {svgedit.draw.Drawing} currentDrawing + */ +svgedit.draw.randomizeIds = function(enableRandomization, currentDrawing) { + randomize_ids = enableRandomization === false ? + RandomizeModes.NEVER_RANDOMIZE : + RandomizeModes.ALWAYS_RANDOMIZE; + + if (randomize_ids == RandomizeModes.ALWAYS_RANDOMIZE && !currentDrawing.getNonce()) { + currentDrawing.setNonce(Math.floor(Math.random() * 100001)); + } else if (randomize_ids == RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) { + currentDrawing.clearNonce(); + } +}; + +/** + * This class encapsulates the concept of a SVG-edit drawing + * @param {SVGSVGElement} svgElem - The SVG DOM Element that this JS object + * encapsulates. If the svgElem has a se:nonce attribute on it, then + * IDs will use the nonce as they are generated. + * @param {String=svg_} [opt_idPrefix] - The ID prefix to use. + */ +svgedit.draw.Drawing = function(svgElem, opt_idPrefix) { + if (!svgElem || !svgElem.tagName || !svgElem.namespaceURI || + svgElem.tagName != 'svg' || svgElem.namespaceURI != NS.SVG) { + throw "Error: svgedit.draw.Drawing instance initialized without a element"; + } + + /** + * The SVG DOM Element that represents this drawing. + * @type {SVGSVGElement} + */ + this.svgElem_ = svgElem; + + /** + * The latest object number used in this drawing. + * @type {number} + */ + this.obj_num = 0; + + /** + * The prefix to prepend to each element id in the drawing. + * @type {String} + */ + this.idPrefix = opt_idPrefix || "svg_"; + + /** + * An array of released element ids to immediately reuse. + * @type {Array.} + */ + this.releasedNums = []; + + /** + * The z-ordered array of tuples containing layer names and elements. + * The first layer is the one at the bottom of the rendering. + * TODO: Turn this into an Array. + * @type {Array.>} + */ + this.all_layers = []; + + /** + * The current layer being used. + * TODO: Make this a {Layer}. + * @type {SVGGElement} + */ + this.current_layer = null; + + /** + * The nonce to use to uniquely identify elements across drawings. + * @type {!String} + */ + this.nonce_ = ''; + var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce'); + // If already set in the DOM, use the nonce throughout the document + // else, if randomizeIds(true) has been called, create and set the nonce. + if (!!n && randomize_ids != RandomizeModes.NEVER_RANDOMIZE) { + this.nonce_ = n; + } else if (randomize_ids == RandomizeModes.ALWAYS_RANDOMIZE) { + this.setNonce(Math.floor(Math.random() * 100001)); + } +}; + +/** + * @param {string} id Element ID to retrieve + * @returns {Element} SVG element within the root SVGSVGElement +*/ +svgedit.draw.Drawing.prototype.getElem_ = function (id) { + if (this.svgElem_.querySelector) { + // querySelector lookup + return this.svgElem_.querySelector('#' + id); + } + // jQuery lookup: twice as slow as xpath in FF + return $(this.svgElem_).find('[id=' + id + ']')[0]; +}; + +/** + * @returns {SVGSVGElement} + */ +svgedit.draw.Drawing.prototype.getSvgElem = function () { + return this.svgElem_; +}; + +/** + * @returns {!string|number} The previously set nonce + */ +svgedit.draw.Drawing.prototype.getNonce = function() { + return this.nonce_; +}; + +/** + * @param {!string|number} n The nonce to set + */ +svgedit.draw.Drawing.prototype.setNonce = function(n) { + this.svgElem_.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE); + this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n); + this.nonce_ = n; +}; + +/** + * Clears any previously set nonce + */ +svgedit.draw.Drawing.prototype.clearNonce = function () { + // We deliberately leave any se:nonce attributes alone, + // we just don't use it to randomize ids. + this.nonce_ = ''; +}; + +/** + * Returns the latest object id as a string. + * @return {String} The latest object Id. + */ +svgedit.draw.Drawing.prototype.getId = function () { + return this.nonce_ ? + this.idPrefix + this.nonce_ + '_' + this.obj_num : + this.idPrefix + this.obj_num; +}; + +/** + * Returns the next object Id as a string. + * @return {String} The next object Id to use. + */ +svgedit.draw.Drawing.prototype.getNextId = function () { + var oldObjNum = this.obj_num; + var restoreOldObjNum = false; + + // If there are any released numbers in the release stack, + // use the last one instead of the next obj_num. + // We need to temporarily use obj_num as that is what getId() depends on. + if (this.releasedNums.length > 0) { + this.obj_num = this.releasedNums.pop(); + restoreOldObjNum = true; + } else { + // If we are not using a released id, then increment the obj_num. + this.obj_num++; + } + + // Ensure the ID does not exist. + var id = this.getId(); + while (this.getElem_(id)) { + if (restoreOldObjNum) { + this.obj_num = oldObjNum; + restoreOldObjNum = false; + } + this.obj_num++; + id = this.getId(); + } + // Restore the old object number if required. + if (restoreOldObjNum) { + this.obj_num = oldObjNum; + } + return id; +}; + +/** + * Releases the object Id, letting it be used as the next id in getNextId(). + * This method DOES NOT remove any elements from the DOM, it is expected + * that client code will do this. + * @param {string} id - The id to release. + * @returns {boolean} True if the id was valid to be released, false otherwise. +*/ +svgedit.draw.Drawing.prototype.releaseId = function (id) { + // confirm if this is a valid id for this Document, else return false + var front = this.idPrefix + (this.nonce_ ? this.nonce_ + '_' : ''); + if (typeof id !== 'string' || id.indexOf(front) !== 0) { + return false; + } + // extract the obj_num of this id + var num = parseInt(id.substr(front.length), 10); + + // if we didn't get a positive number or we already released this number + // then return false. + if (typeof num !== 'number' || num <= 0 || this.releasedNums.indexOf(num) != -1) { + return false; + } + + // push the released number into the released queue + this.releasedNums.push(num); + + return true; +}; + +/** + * Returns the number of layers in the current drawing. + * @returns {integer} The number of layers in the current drawing. +*/ +svgedit.draw.Drawing.prototype.getNumLayers = function() { + return this.all_layers.length; +}; + +/** + * Check if layer with given name already exists + * @param {string} name - The layer name to check +*/ +svgedit.draw.Drawing.prototype.hasLayer = function (name) { + var i; + for (i = 0; i < this.getNumLayers(); i++) { + if(this.all_layers[i][0] == name) {return true;} + } + return false; +}; + + +/** + * Returns the name of the ith layer. If the index is out of range, an empty string is returned. + * @param {integer} i - The zero-based index of the layer you are querying. + * @returns {string} The name of the ith layer (or the empty string if none found) +*/ +svgedit.draw.Drawing.prototype.getLayerName = function (i) { + if (i >= 0 && i < this.getNumLayers()) { + return this.all_layers[i][0]; + } + return ''; +}; + +/** + * @returns {SVGGElement} The SVGGElement representing the current layer. + */ +svgedit.draw.Drawing.prototype.getCurrentLayer = function() { + return this.current_layer; +}; + +/** + * Returns the name of the currently selected layer. If an error occurs, an empty string + * is returned. + * @returns The name of the currently active layer (or the empty string if none found). +*/ +svgedit.draw.Drawing.prototype.getCurrentLayerName = function () { + var i; + for (i = 0; i < this.getNumLayers(); ++i) { + if (this.all_layers[i][1] == this.current_layer) { + return this.getLayerName(i); + } + } + return ''; +}; + +/** + * Sets the current layer. If the name is not a valid layer name, then this + * function returns false. Otherwise it returns true. This is not an + * undo-able action. + * @param {string} name - The name of the layer you want to switch to. + * @returns {boolean} true if the current layer was switched, otherwise false + */ +svgedit.draw.Drawing.prototype.setCurrentLayer = function(name) { + var i; + for (i = 0; i < this.getNumLayers(); ++i) { + if (name == this.getLayerName(i)) { + if (this.current_layer != this.all_layers[i][1]) { + this.current_layer.setAttribute("style", "pointer-events:none"); + this.current_layer = this.all_layers[i][1]; + this.current_layer.setAttribute("style", "pointer-events:all"); + } + return true; + } + } + return false; +}; + + +/** + * Deletes the current layer from the drawing and then clears the selection. + * This function then calls the 'changed' handler. This is an undoable action. + * @returns {SVGGElement} The SVGGElement of the layer removed or null. + */ +svgedit.draw.Drawing.prototype.deleteCurrentLayer = function() { + if (this.current_layer && this.getNumLayers() > 1) { + // actually delete from the DOM and return it + var parent = this.current_layer.parentNode; + var nextSibling = this.current_layer.nextSibling; + var oldLayerGroup = parent.removeChild(this.current_layer); + this.identifyLayers(); + return oldLayerGroup; + } + return null; +}; + +/** + * Updates layer system and sets the current layer to the + * top-most layer (last child of this drawing). +*/ +svgedit.draw.Drawing.prototype.identifyLayers = function() { + this.all_layers = []; + var numchildren = this.svgElem_.childNodes.length; + // loop through all children of SVG element + var orphans = [], layernames = []; + var a_layer = null; + var childgroups = false; + var i; + for (i = 0; i < numchildren; ++i) { + var child = this.svgElem_.childNodes.item(i); + // for each g, find its layer name + if (child && child.nodeType == 1) { + if (child.tagName == "g") { + childgroups = true; + var name = $("title", child).text(); + + // Hack for Opera 10.60 + if(!name && svgedit.browser.isOpera() && child.querySelectorAll) { + name = $(child.querySelectorAll('title')).text(); + } + + // store layer and name in global variable + if (name) { + layernames.push(name); + this.all_layers.push( [name, child] ); + a_layer = child; + svgedit.utilities.walkTree(child, function(e){e.setAttribute("style", "pointer-events:inherit");}); + a_layer.setAttribute("style", "pointer-events:none"); + } + // if group did not have a name, it is an orphan + else { + orphans.push(child); + } + } + // if child has is "visible" (i.e. not a or element), then it is an orphan + else if(~visElems.indexOf(child.nodeName)) { + var bb = svgedit.utilities.getBBox(child); + orphans.push(child); + } + } + } + + // create a new layer and add all the orphans to it + var svgdoc = this.svgElem_.ownerDocument; + if (orphans.length > 0 || !childgroups) { + i = 1; + // TODO(codedread): What about internationalization of "Layer"? + while (layernames.indexOf(("Layer " + i)) >= 0) { i++; } + var newname = "Layer " + i; + a_layer = svgdoc.createElementNS(NS.SVG, "g"); + var layer_title = svgdoc.createElementNS(NS.SVG, "title"); + layer_title.textContent = newname; + a_layer.appendChild(layer_title); + var j; + for (j = 0; j < orphans.length; ++j) { + a_layer.appendChild(orphans[j]); + } + this.svgElem_.appendChild(a_layer); + this.all_layers.push( [newname, a_layer] ); + } + svgedit.utilities.walkTree(a_layer, function(e){e.setAttribute("style", "pointer-events:inherit");}); + this.current_layer = a_layer; + this.current_layer.setAttribute("style", "pointer-events:all"); +}; + +/** + * Creates a new top-level layer in the drawing with the given name and + * sets the current layer to it. + * @param {string} name - The given name + * @returns {SVGGElement} The SVGGElement of the new layer, which is + * also the current layer of this drawing. +*/ +svgedit.draw.Drawing.prototype.createLayer = function(name) { + var svgdoc = this.svgElem_.ownerDocument; + var new_layer = svgdoc.createElementNS(NS.SVG, "g"); + var layer_title = svgdoc.createElementNS(NS.SVG, "title"); + layer_title.textContent = name; + new_layer.appendChild(layer_title); + this.svgElem_.appendChild(new_layer); + this.identifyLayers(); + return new_layer; +}; + +/** + * Returns whether the layer is visible. If the layer name is not valid, + * then this function returns false. + * @param {string} layername - The name of the layer which you want to query. + * @returns {boolean} The visibility state of the layer, or false if the layer name was invalid. +*/ +svgedit.draw.Drawing.prototype.getLayerVisibility = function(layername) { + // find the layer + var layer = null; + var i; + for (i = 0; i < this.getNumLayers(); ++i) { + if (this.getLayerName(i) == layername) { + layer = this.all_layers[i][1]; + break; + } + } + if (!layer) {return false;} + return (layer.getAttribute('display') !== 'none'); +}; + +/** + * Sets the visibility of the layer. If the layer name is not valid, this + * function returns false, otherwise it returns true. This is an + * undo-able action. + * @param {string} layername - The name of the layer to change the visibility + * @param {boolean} bVisible - Whether the layer should be visible + * @returns {?SVGGElement} The SVGGElement representing the layer if the + * layername was valid, otherwise null. +*/ +svgedit.draw.Drawing.prototype.setLayerVisibility = function(layername, bVisible) { + if (typeof bVisible !== 'boolean') { + return null; + } + // find the layer + var layer = null; + var i; + for (i = 0; i < this.getNumLayers(); ++i) { + if (this.getLayerName(i) == layername) { + layer = this.all_layers[i][1]; + break; + } + } + if (!layer) {return null;} + + var oldDisplay = layer.getAttribute("display"); + if (!oldDisplay) {oldDisplay = "inline";} + layer.setAttribute("display", bVisible ? "inline" : "none"); + return layer; +}; + + +/** + * Returns the opacity of the given layer. If the input name is not a layer, null is returned. + * @param {string} layername - name of the layer on which to get the opacity + * @returns {?number} The opacity value of the given layer. This will be a value between 0.0 and 1.0, or null + * if layername is not a valid layer +*/ +svgedit.draw.Drawing.prototype.getLayerOpacity = function(layername) { + var i; + for (i = 0; i < this.getNumLayers(); ++i) { + if (this.getLayerName(i) == layername) { + var g = this.all_layers[i][1]; + var opacity = g.getAttribute('opacity'); + if (!opacity) { + opacity = '1.0'; + } + return parseFloat(opacity); + } + } + return null; +}; + +/** + * Sets the opacity of the given layer. If the input name is not a layer, + * nothing happens. If opacity is not a value between 0.0 and 1.0, then + * nothing happens. + * @param {string} layername - Name of the layer on which to set the opacity + * @param {number} opacity - A float value in the range 0.0-1.0 +*/ +svgedit.draw.Drawing.prototype.setLayerOpacity = function(layername, opacity) { + if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) { + return; + } + var i; + for (i = 0; i < this.getNumLayers(); ++i) { + if (this.getLayerName(i) == layername) { + var g = this.all_layers[i][1]; + g.setAttribute("opacity", opacity); + break; + } + } +}; + +}()); diff --git a/content/media/2015/03/svg-edit-2.7/embedapi.html b/content/media/2015/03/svg-edit-2.7/embedapi.html new file mode 100755 index 0000000..cea5cfc --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/embedapi.html @@ -0,0 +1,59 @@ + + + + + Embed API + + + + + + + +
    + + diff --git a/content/media/2015/03/svg-edit-2.7/embedapi.js b/content/media/2015/03/svg-edit-2.7/embedapi.js new file mode 100755 index 0000000..7024789 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/embedapi.js @@ -0,0 +1,187 @@ +/* +Embedded SVG-edit API + +General usage: +- Have an iframe somewhere pointing to a version of svg-edit > r1000 +- Initialize the magic with: +var svgCanvas = new EmbeddedSVGEdit(window.frames.svgedit); +- Pass functions in this format: +svgCanvas.setSvgString('string') +- Or if a callback is needed: +svgCanvas.setSvgString('string')(function(data, error){ + if (error){ + // There was an error + } else{ + // Handle data + } +}) + +Everything is done with the same API as the real svg-edit, +and all documentation is unchanged. + +However, this file depends on the postMessage API which +can only support JSON-serializable arguments and +return values, so, for example, arguments whose value is +'undefined', a function, a non-finite number, or a built-in +object like Date(), RegExp(), etc. will most likely not behave +as expected. In such a case one may need to host +the SVG editor on the same domain and reference the +JavaScript methods on the frame itself. + +The only other difference is +when handling returns: the callback notation is used instead. + +var blah = new EmbeddedSVGEdit(window.frames.svgedit); +blah.clearSelection('woot', 'blah', 1337, [1, 2, 3, 4, 5, 'moo'], -42, {a: 'tree',b:6, c: 9})(function(){console.log('GET DATA',arguments)}) +*/ + +(function () {'use strict'; + +var cbid = 0; + +function getCallbackSetter (d) { + return function () { + var t = this, // New callback + args = [].slice.call(arguments), + cbid = t.send(d, args, function(){}); // The callback (currently it's nothing, but will be set later) + + return function(newcallback){ + t.callbacks[cbid] = newcallback; // Set callback + }; + }; +} + +/* +* Having this separate from messageListener allows us to +* avoid using JSON parsing (and its limitations) in the case +* of same domain control +*/ +function addCallback (t, data) { + var result = data.result || data.error; + cbid = data.id; + if (t.callbacks[cbid]) { + if (data.result) { + t.callbacks[cbid](result); + } else { + t.callbacks[cbid](result, 'error'); + } + } +} + +function messageListener (e) { + // We accept and post strings as opposed to objects for the sake of IE9 support; this + // will most likely be changed in the future + if (typeof e.data !== 'string') { + return; + } + var allowedOrigins = this.allowedOrigins, + data = e.data && JSON.parse(e.data); + if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit' || + e.source !== this.frame.contentWindow || + (allowedOrigins.indexOf('*') === -1 && allowedOrigins.indexOf(e.origin) === -1) + ) { + return; + } + addCallback(this, data); +} + +function getMessageListener (t) { + return function (e) { + messageListener.call(t, e); + }; +} + +/** +* @param {HTMLIFrameElement} frame +* @param {array} [allowedOrigins=[]] Array of origins from which incoming +* messages will be allowed when same origin is not used; defaults to none. +* If supplied, it should probably be the same as svgEditor's allowedOrigins +*/ +function EmbeddedSVGEdit (frame, allowedOrigins) { + if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without 'new' keyword + return new EmbeddedSVGEdit(frame); + } + this.allowedOrigins = allowedOrigins || []; + // Initialize communication + this.frame = frame; + this.callbacks = {}; + // List of functions extracted with this: + // Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html + + // for (var i=0,q=[],f = document.querySelectorAll('div.CFunction h3.CTitle a'); i < f.length; i++) { q.push(f[i].name); }; q + // var functions = ['clearSelection', 'addToSelection', 'removeFromSelection', 'open', 'save', 'getSvgString', 'setSvgString', + // 'createLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', + // 'moveSelectedToLayer', 'clear']; + + // Newer, well, it extracts things that aren't documented as well. All functions accessible through the normal thingy can now be accessed though the API + // var l = []; for (var i in svgCanvas){ if (typeof svgCanvas[i] == 'function') { l.push(i);} }; + // Run in svgedit itself + var i, + functions = ['updateElementFromJson', 'embedImage', 'fixOperaXML', 'clearSelection', + 'addToSelection', + 'removeFromSelection', 'addNodeToSelection', 'open', 'save', 'getSvgString', 'setSvgString', 'createLayer', + 'deleteCurrentLayer', 'getCurrentDrawing', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', + 'setLayerVisibility', 'moveSelectedToLayer', 'clear', 'clearPath', 'getNodePoint', 'clonePathNode', 'deletePathNode', + 'getResolution', 'getImageTitle', 'setImageTitle', 'setResolution', 'setBBoxZoom', 'setZoom', 'getMode', 'setMode', + 'getStrokeColor', 'setStrokeColor', 'getFillColor', 'setFillColor', 'setStrokePaint', 'setFillPaint', 'getStrokeWidth', + 'setStrokeWidth', 'getStrokeStyle', 'setStrokeStyle', 'getOpacity', 'setOpacity', 'getFillOpacity', 'setFillOpacity', + 'getStrokeOpacity', 'setStrokeOpacity', 'getTransformList', 'getBBox', 'getRotationAngle', 'setRotationAngle', 'each', + 'bind', 'setIdPrefix', 'getBold', 'setBold', 'getItalic', 'setItalic', 'getFontFamily', 'setFontFamily', 'getFontSize', + 'setFontSize', 'getText', 'setTextContent', 'setImageURL', 'setRectRadius', 'setSegType', 'quickClone', + 'changeSelectedAttributeNoUndo', 'changeSelectedAttribute', 'deleteSelectedElements', 'groupSelectedElements', 'zoomChanged', + 'ungroupSelectedElement', 'moveToTopSelectedElement', 'moveToBottomSelectedElement', 'moveSelectedElements', + 'getStrokedBBox', 'getVisibleElements', 'cycleElement', 'getUndoStackSize', 'getRedoStackSize', 'getNextUndoCommandText', + 'getNextRedoCommandText', 'undo', 'redo', 'cloneSelectedElements', 'alignSelectedElements', 'getZoom', 'getVersion', + 'setIconSize', 'setLang', 'setCustomHandlers']; + + // TODO: rewrite the following, it's pretty scary. + for (i = 0; i < functions.length; i++) { + this[functions[i]] = getCallbackSetter(functions[i]); + } + + // Older IE may need a polyfill for addEventListener, but so it would for SVG + window.addEventListener('message', getMessageListener(this), false); +} + +EmbeddedSVGEdit.prototype.send = function (name, args, callback){ + var t = this; + cbid++; + + this.callbacks[cbid] = callback; + setTimeout(function () { // Delay for the callback to be set in case its synchronous + /* + * Todo: Handle non-JSON arguments and return values (undefined, + * nonfinite numbers, functions, and built-in objects like Date, + * RegExp), etc.? Allow promises instead of callbacks? Review + * SVG-Edit functions for whether JSON-able parameters can be + * made compatile with all API functionality + */ + // We accept and post strings for the sake of IE9 support + if (window.location.origin === t.frame.contentWindow.location.origin) { + // Although we do not really need this API if we are working same + // domain, it could allow us to write in a way that would work + // cross-domain as well, assuming we stick to the argument limitations + // of the current JSON-based communication API (e.g., not passing + // callbacks). We might be able to address these shortcomings; see + // the todo elsewhere in this file. + var message = {id: cbid}, + svgCanvas = t.frame.contentWindow.svgCanvas; + try { + message.result = svgCanvas[name].apply(svgCanvas, args); + } + catch (err) { + message.error = err.message; + } + addCallback(t, message); + } + else { // Requires the ext-xdomain-messaging.js extension + t.frame.contentWindow.postMessage(JSON.stringify({namespace: 'svgCanvas', id: cbid, name: name, args: args}), '*'); + } + }, 0); + return cbid; +}; + +window.embedded_svg_edit = EmbeddedSVGEdit; // Export old, deprecated API +window.EmbeddedSVGEdit = EmbeddedSVGEdit; // Follows common JS convention of CamelCase and, as enforced in JSLint, of initial caps for constructors + +}()); diff --git a/content/media/2015/03/svg-edit-2.7/extensions/allowedMimeTypes.php b/content/media/2015/03/svg-edit-2.7/extensions/allowedMimeTypes.php new file mode 100755 index 0000000..1e932b8 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/extensions/allowedMimeTypes.php @@ -0,0 +1,11 @@ + 'image/svg+xml;charset=utf-8', + 'png' => 'image/png', + 'jpeg' => 'image/jpeg', + 'bmp' => 'image/bmp', + 'webp' => 'image/webp' +); + +?> \ No newline at end of file diff --git a/content/media/2015/03/svg-edit-2.7/extensions/closepath_icons.svg b/content/media/2015/03/svg-edit-2.7/extensions/closepath_icons.svg new file mode 100755 index 0000000..7294f5e --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/extensions/closepath_icons.svg @@ -0,0 +1,41 @@ + + + + + Layer 1 + + + + + + + + + + + + + + + + + Layer 1 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/media/2015/03/svg-edit-2.7/extensions/executablebuilder-icocreator.svg b/content/media/2015/03/svg-edit-2.7/extensions/executablebuilder-icocreator.svg new file mode 100755 index 0000000..7c68adf --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/extensions/executablebuilder-icocreator.svg @@ -0,0 +1,9 @@ + + + + Layer 1 + + ICO + + + \ No newline at end of file diff --git a/content/media/2015/03/svg-edit-2.7/extensions/ext-arrows.js b/content/media/2015/03/svg-edit-2.7/extensions/ext-arrows.js new file mode 100755 index 0000000..6bf9b3f --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/extensions/ext-arrows.js @@ -0,0 +1,293 @@ +/*globals svgEditor, svgCanvas, $*/ +/*jslint vars: true, eqeq: true*/ +/* + * ext-arrows.js + * + * Licensed under the MIT License + * + * Copyright(c) 2010 Alexis Deveria + * + */ + +svgEditor.addExtension('Arrows', function(S) { + var svgcontent = S.svgcontent, + addElem = S.addSvgElementFromJson, + nonce = S.nonce, + randomize_ids = S.randomize_ids, + selElems, pathdata, + lang_list = { + 'en':[ + {'id': 'arrow_none', 'textContent': 'No arrow' } + ], + 'fr':[ + {'id': 'arrow_none', 'textContent': 'Sans flèche' } + ] + }, + arrowprefix, + prefix = 'se_arrow_'; + + function setArrowNonce(window, n) { + randomize_ids = true; + arrowprefix = prefix + n + '_'; + pathdata.fw.id = arrowprefix + 'fw'; + pathdata.bk.id = arrowprefix + 'bk'; + } + + function unsetArrowNonce(window) { + randomize_ids = false; + arrowprefix = prefix; + pathdata.fw.id = arrowprefix + 'fw'; + pathdata.bk.id = arrowprefix + 'bk'; + } + + + svgCanvas.bind('setnonce', setArrowNonce); + svgCanvas.bind('unsetnonce', unsetArrowNonce); + + if (randomize_ids) { + arrowprefix = prefix + nonce + '_'; + } else { + arrowprefix = prefix; + } + + pathdata = { + fw: {d: 'm0,0l10,5l-10,5l5,-5l-5,-5z', refx: 8, id: arrowprefix + 'fw'}, + bk: {d: 'm10,0l-10,5l10,5l-5,-5l5,-5z', refx: 2, id: arrowprefix + 'bk'} + }; + + function getLinked(elem, attr) { + var str = elem.getAttribute(attr); + if(!str) {return null;} + var m = str.match(/\(\#(.*)\)/); + if(!m || m.length !== 2) { + return null; + } + return S.getElem(m[1]); + } + + function showPanel(on) { + $('#arrow_panel').toggle(on); + if(on) { + var el = selElems[0]; + var end = el.getAttribute('marker-end'); + var start = el.getAttribute('marker-start'); + var mid = el.getAttribute('marker-mid'); + var val; + + if (end && start) { + val = 'both'; + } else if (end) { + val = 'end'; + } else if (start) { + val = 'start'; + } else if (mid) { + val = 'mid'; + if (mid.indexOf('bk') !== -1) { + val = 'mid_bk'; + } + } + + if (!start && !mid && !end) { + val = 'none'; + } + + $('#arrow_list').val(val); + } + } + + function resetMarker() { + var el = selElems[0]; + el.removeAttribute('marker-start'); + el.removeAttribute('marker-mid'); + el.removeAttribute('marker-end'); + } + + function addMarker(dir, type, id) { + // TODO: Make marker (or use?) per arrow type, since refX can be different + id = id || arrowprefix + dir; + + var marker = S.getElem(id); + var data = pathdata[dir]; + + if (type == 'mid') { + data.refx = 5; + } + + if (!marker) { + marker = addElem({ + 'element': 'marker', + 'attr': { + 'viewBox': '0 0 10 10', + 'id': id, + 'refY': 5, + 'markerUnits': 'strokeWidth', + 'markerWidth': 5, + 'markerHeight': 5, + 'orient': 'auto', + 'style': 'pointer-events:none' // Currently needed for Opera + } + }); + var arrow = addElem({ + 'element': 'path', + 'attr': { + 'd': data.d, + 'fill': '#000000' + } + }); + marker.appendChild(arrow); + S.findDefs().appendChild(marker); + } + + marker.setAttribute('refX', data.refx); + + return marker; + } + + function setArrow() { + var type = this.value; + resetMarker(); + + if (type == 'none') { + return; + } + + // Set marker on element + var dir = 'fw'; + if (type == 'mid_bk') { + type = 'mid'; + dir = 'bk'; + } else if (type == 'both') { + addMarker('bk', type); + svgCanvas.changeSelectedAttribute('marker-start', 'url(#' + pathdata.bk.id + ')'); + type = 'end'; + dir = 'fw'; + } else if (type == 'start') { + dir = 'bk'; + } + + addMarker(dir, type); + svgCanvas.changeSelectedAttribute('marker-' + type, 'url(#' + pathdata[dir].id + ')'); + S.call('changed', selElems); + } + + function colorChanged(elem) { + var color = elem.getAttribute('stroke'); + var mtypes = ['start', 'mid', 'end']; + var defs = S.findDefs(); + + $.each(mtypes, function(i, type) { + var marker = getLinked(elem, 'marker-'+type); + if(!marker) {return;} + + var cur_color = $(marker).children().attr('fill'); + var cur_d = $(marker).children().attr('d'); + var new_marker = null; + if(cur_color === color) {return;} + + var all_markers = $(defs).find('marker'); + // Different color, check if already made + all_markers.each(function() { + var attrs = $(this).children().attr(['fill', 'd']); + if(attrs.fill === color && attrs.d === cur_d) { + // Found another marker with this color and this path + new_marker = this; + } + }); + + if(!new_marker) { + // Create a new marker with this color + var last_id = marker.id; + var dir = last_id.indexOf('_fw') !== -1?'fw':'bk'; + + new_marker = addMarker(dir, type, arrowprefix + dir + all_markers.length); + + $(new_marker).children().attr('fill', color); + } + + $(elem).attr('marker-'+type, 'url(#' + new_marker.id + ')'); + + // Check if last marker can be removed + var remove = true; + $(S.svgcontent).find('line, polyline, path, polygon').each(function() { + var elem = this; + $.each(mtypes, function(j, mtype) { + if($(elem).attr('marker-' + mtype) === 'url(#' + marker.id + ')') { + remove = false; + return remove; + } + }); + if(!remove) {return false;} + }); + + // Not found, so can safely remove + if(remove) { + $(marker).remove(); + } + }); + } + + return { + name: 'Arrows', + context_tools: [{ + type: 'select', + panel: 'arrow_panel', + title: 'Select arrow type', + id: 'arrow_list', + options: { + none: 'No arrow', + end: '---->', + start: '<----', + both: '<--->', + mid: '-->--', + mid_bk: '--<--' + }, + defval: 'none', + events: { + change: setArrow + } + }], + callback: function() { + $('#arrow_panel').hide(); + // Set ID so it can be translated in locale file + $('#arrow_list option')[0].id = 'connector_no_arrow'; + }, + addLangData: function(lang) { + return { + data: lang_list[lang] + }; + }, + selectedChanged: function(opts) { + // Use this to update the current selected elements + selElems = opts.elems; + + var i = selElems.length; + var marker_elems = ['line', 'path', 'polyline', 'polygon']; + while(i--) { + var elem = selElems[i]; + if(elem && $.inArray(elem.tagName, marker_elems) !== -1) { + if(opts.selectedElement && !opts.multiselected) { + showPanel(true); + } else { + showPanel(false); + } + } else { + showPanel(false); + } + } + }, + elementChanged: function(opts) { + var elem = opts.elems[0]; + if(elem && ( + elem.getAttribute('marker-start') || + elem.getAttribute('marker-mid') || + elem.getAttribute('marker-end') + )) { +// var start = elem.getAttribute('marker-start'); +// var mid = elem.getAttribute('marker-mid'); +// var end = elem.getAttribute('marker-end'); + // Has marker, so see if it should match color + colorChanged(elem); + } + } + }; +}); diff --git a/content/media/2015/03/svg-edit-2.7/extensions/ext-closepath.js b/content/media/2015/03/svg-edit-2.7/extensions/ext-closepath.js new file mode 100755 index 0000000..b785842 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/extensions/ext-closepath.js @@ -0,0 +1,91 @@ +/*globals svgEditor, $*/ +/*jslint vars: true, eqeq: true*/ +/* + * ext-closepath.js + * + * Licensed under the MIT License + * + * Copyright(c) 2010 Jeff Schiller + * + */ + +// This extension adds a simple button to the contextual panel for paths +// The button toggles whether the path is open or closed +svgEditor.addExtension('ClosePath', function() {'use strict'; + var selElems, + updateButton = function(path) { + var seglist = path.pathSegList, + closed = seglist.getItem(seglist.numberOfItems - 1).pathSegType == 1, + showbutton = closed ? '#tool_openpath' : '#tool_closepath', + hidebutton = closed ? '#tool_closepath' : '#tool_openpath'; + $(hidebutton).hide(); + $(showbutton).show(); + }, + showPanel = function(on) { + $('#closepath_panel').toggle(on); + if (on) { + var path = selElems[0]; + if (path) {updateButton(path);} + } + }, + toggleClosed = function() { + var path = selElems[0]; + if (path) { + var seglist = path.pathSegList, + last = seglist.numberOfItems - 1; + // is closed + if (seglist.getItem(last).pathSegType == 1) { + seglist.removeItem(last); + } else { + seglist.appendItem(path.createSVGPathSegClosePath()); + } + updateButton(path); + } + }; + + return { + name: 'ClosePath', + svgicons: svgEditor.curConfig.extPath + 'closepath_icons.svg', + buttons: [{ + id: 'tool_openpath', + type: 'context', + panel: 'closepath_panel', + title: 'Open path', + events: { + click: function() { + toggleClosed(); + } + } + }, + { + id: 'tool_closepath', + type: 'context', + panel: 'closepath_panel', + title: 'Close path', + events: { + click: function() { + toggleClosed(); + } + } + }], + callback: function() { + $('#closepath_panel').hide(); + }, + selectedChanged: function(opts) { + selElems = opts.elems; + var i = selElems.length; + while (i--) { + var elem = selElems[i]; + if (elem && elem.tagName == 'path') { + if (opts.selectedElement && !opts.multiselected) { + showPanel(true); + } else { + showPanel(false); + } + } else { + showPanel(false); + } + } + } + }; +}); diff --git a/content/media/2015/03/svg-edit-2.7/extensions/ext-connector.js b/content/media/2015/03/svg-edit-2.7/extensions/ext-connector.js new file mode 100755 index 0000000..85d857e --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/extensions/ext-connector.js @@ -0,0 +1,593 @@ +/*globals svgEditor, svgCanvas, $*/ +/*jslint vars: true, continue: true, eqeq: true, todo: true*/ +/* + * ext-connector.js + * + * Licensed under the MIT License + * + * Copyright(c) 2010 Alexis Deveria + * + */ + +svgEditor.addExtension("Connector", function(S) { + var svgcontent = S.svgcontent, + svgroot = S.svgroot, + getNextId = S.getNextId, + getElem = S.getElem, + addElem = S.addSvgElementFromJson, + selManager = S.selectorManager, + curConfig = svgEditor.curConfig, + started = false, + start_x, + start_y, + cur_line, + start_elem, + end_elem, + connections = [], + conn_sel = ".se_connector", + se_ns, +// connect_str = "-SE_CONNECT-", + selElems = [], + elData = $.data; + + var lang_list = { + "en":[ + {"id": "mode_connect", "title": "Connect two objects" } + ], + "fr":[ + {"id": "mode_connect", "title": "Connecter deux objets"} + ] + }; + + function getBBintersect(x, y, bb, offset) { + if(offset) { + offset -= 0; + bb = $.extend({}, bb); + bb.width += offset; + bb.height += offset; + bb.x -= offset/2; + bb.y -= offset/2; + } + + var mid_x = bb.x + bb.width/2; + var mid_y = bb.y + bb.height/2; + var len_x = x - mid_x; + var len_y = y - mid_y; + + var slope = Math.abs(len_y/len_x); + + var ratio; + + if(slope < bb.height/bb.width) { + ratio = (bb.width/2) / Math.abs(len_x); + } else { + ratio = (bb.height/2) / Math.abs(len_y); + } + + + return { + x: mid_x + len_x * ratio, + y: mid_y + len_y * ratio + }; + } + + function getOffset(side, line) { + var give_offset = !!line.getAttribute('marker-' + side); +// var give_offset = $(line).data(side+'_off'); + + // TODO: Make this number (5) be based on marker width/height + var size = line.getAttribute('stroke-width') * 5; + return give_offset ? size : 0; + } + + function showPanel(on) { + var conn_rules = $('#connector_rules'); + if(!conn_rules.length) { + conn_rules = $(' +
    + +
    + + +
    +
    +

    Layers

    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + + +
    Layer 1
    + Move elements to: + +
    +
    L a y e r s
    +
    + +
    +
    + SVG-Edit + + +
    + + +
    + + + +
    + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    + + + +
    + + +
    + + + +
    + + +
    +
    + + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    + +
    + +
    +
    + + +
    + +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    B
    +
    i
    +
    + +
    + + +
    + + + + + +
    + + +
    +
    + + + + +
    + +
    + +
    + +
    +
    +
    + + +
    + +
    + +
    +
    + +
    + + + + +
    +
    +
    +
    +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + +
    + + +
    +
    + +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + + + +
    + + + + + + + +
    + +
    + + +
    +
    + +
    + +
    +
    +
    + +
    + + + + + +
    + + + +
    +
    +
    +
    + + +
    +
    +

    Copy the contents of this box into a text editor, then save the file with a .svg extension.

    + +
    +
    + +
    +
    +
    + + +
    +
    +
    +
    + + +
    + + +
    + Image Properties + + +
    + Canvas Dimensions + + + + + + +
    + +
    + Included Images + + +
    +
    + +
    +
    + +
    +
    +
    +
    + + +
    + +
    + Editor Preferences + + + + + +
    + Editor Background +
    + +

    Note: Background will not be saved with image.

    +
    + +
    + Grid + + + +
    + +
    + Units & Rulers + + + + +
    + +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/LICENSE b/content/media/2015/03/svg-edit-2.7/jgraduate/LICENSE new file mode 100755 index 0000000..d645695 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/jgraduate/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/README b/content/media/2015/03/svg-edit-2.7/jgraduate/README new file mode 100755 index 0000000..ef3e21f --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/jgraduate/README @@ -0,0 +1,3 @@ +jGraduate - A jQuery plugin for picking gradients + +Licensed under the Apache License 2. See LICENSE for more information. diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/css/jPicker.css b/content/media/2015/03/svg-edit-2.7/jgraduate/css/jPicker.css new file mode 100755 index 0000000..d186af7 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/jgraduate/css/jPicker.css @@ -0,0 +1 @@ +.jPicker .Icon{display:inline-block;height:24px;position:relative;text-align:left;width:25px}.jPicker .Icon span.Color,.jPicker .Icon span.Alpha{background-position:2px 2px;display:block;height:100%;left:0;position:absolute;top:0;width:100%}.jPicker .Icon span.Image{background-repeat:no-repeat;cursor:pointer;display:block;height:100%;left:0;position:absolute;top:0;width:100%}.jPicker.Container{z-index:10}table.jPicker{background-color:#efefef;border:1px outset #666;font-family:Arial,Helvetica,Sans-Serif;font-size:12px!important;margin:0;padding:5px;width:545px;z-index:20}.jPicker .Move{background-color:#ddd;border-color:#fff #666 #666 #fff;border-style:solid;border-width:1px;cursor:move;height:12px;padding:0}.jPicker .Title{font-size:11px!important;font-weight:bold;margin:-2px 0 0 0;padding:0;text-align:center;width:100%}.jPicker div.Map{border-bottom:2px solid #fff;border-left:2px solid #9a9a9a;border-right:2px solid #fff;border-top:2px solid #9a9a9a;cursor:crosshair;height:260px;margin:0 5px 0 5px;overflow:hidden;padding:0;position:relative;width:260px}.jPicker div[class="Map"]{height:256px;width:256px}.jPicker div.Bar{border-bottom:2px solid #fff;border-left:2px solid #9a9a9a;border-right:2px solid #fff;border-top:2px solid #9a9a9a;cursor:n-resize;height:260px;margin:12px 10px 0 5px;overflow:hidden;padding:0;position:relative;width:24px}.jPicker div[class="Bar"]{height:256px;width:20px}.jPicker .Map .Map1,.jPicker .Map .Map2,.jPicker .Map .Map3,.jPicker .Bar .Map1,.jPicker .Bar .Map2,.jPicker .Bar .Map3,.jPicker .Bar .Map4,.jPicker .Bar .Map5,.jPicker .Bar .Map6{background-color:transparent;background-image:none;display:block;left:0;position:absolute;top:0}.jPicker .Map .Map1,.jPicker .Map .Map2,.jPicker .Map .Map3{height:2596px;width:256px}.jPicker .Bar .Map1,.jPicker .Bar .Map2,.jPicker .Bar .Map3,.jPicker .Bar .Map4{height:3896px;width:20px}.jPicker .Bar .Map5,.jPicker .Bar .Map6{height:256px;width:20px}.jPicker .Map .Map1,.jPicker .Map .Map2,.jPicker .Bar .Map6{background-repeat:no-repeat}.jPicker .Map .Map3,.jPicker .Bar .Map5{background-repeat:repeat}.jPicker .Bar .Map1,.jPicker .Bar .Map2,.jPicker .Bar .Map3,.jPicker .Bar .Map4{background-repeat:repeat-x}.jPicker .Map .Arrow{display:block;position:absolute}.jPicker .Bar .Arrow{display:block;left:0;position:absolute}.jPicker .Preview{font-size:9px;text-align:center}.jPicker .Preview div{border:2px inset #eee;height:62px;margin:0 auto;padding:0;width:62px}.jPicker .Preview div span{border:1px solid #000;display:block;height:30px;margin:0 auto;padding:0;width:60px}.jPicker .Preview .Active{border-bottom-width:0}.jPicker .Preview .Current{border-top-width:0;cursor:pointer}.jPicker .Button{text-align:center;width:115px}.jPicker .Button input{width:100px}.jPicker .Button .Ok{margin:12px 0 5px 0}.jPicker td.Radio{margin:0;padding:0;width:31px}.jPicker td.Radio input{margin:0 5px 0 0;padding:0}.jPicker td.Text{font-size:12px!important;height:22px;margin:0;padding:0;text-align:left;width:70px}.jPicker tr.Hex td.Text{width:100px}.jPicker td.Text input{background-color:#fff;border:1px inset #aaa;height:19px;margin:0 0 0 5px;text-align:left;width:30px}.jPicker td[class="Text"] input{height:15px}.jPicker tr.Hex td.Text input.Hex{width:50px}.jPicker tr.Hex td.Text input.AHex{width:20px}.jPicker .Grid{text-align:center;width:114px}.jPicker .Grid span.QuickColor{border:1px inset #aaa;cursor:pointer;display:inline-block;height:15px;line-height:15px;margin:0;padding:0;width:19px}.jPicker .Grid span[class="QuickColor"]{width:17px} \ No newline at end of file diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/css/jgraduate.css b/content/media/2015/03/svg-edit-2.7/jgraduate/css/jgraduate.css new file mode 100755 index 0000000..5a9eed3 --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/jgraduate/css/jgraduate.css @@ -0,0 +1,351 @@ +/* + * jGraduate Default CSS + * + * Copyright (c) 2010 Jeff Schiller + * http://blog.codedread.com/ + * + * Copyright (c) 2010 Alexis Deveria + * http://a.deveria.com/ + * + * Licensed under the MIT License + */ + +h2.jGraduate_Title { + font-family: Arial, Helvetica, Sans-Serif; + font-size: 11px !important; + font-weight: bold; + margin: -13px 0px 0px 0px; + padding: 0px; + text-align: center; +} + +.jGraduate_Picker { + font-family: Arial, Helvetica, Sans-Serif; + font-size: 12px; + border-style: solid; + border-color: lightgrey black black lightgrey; + border-width: 1px; + background-color: #EFEFEF; + position: absolute; + padding: 10px; +} + +.jGraduate_tabs li { + background-color: #ccc; + display: inline; + border: solid 1px grey; + padding: 3px; + margin: 2px; + cursor: pointer; +} + +li.jGraduate_tab_current { + background-color: #EFEFEF; + display: inline; + padding: 3px; + margin: 2px; + border: solid 1px black; + cursor: pointer; +} + +.jGraduate_colPick { + display: none; +} + +.jGraduate_gradPick { + display: none; + border: outset 1px #666; + padding: 10px 7px 5px 5px; + overflow: auto; +} + +.jGraduate_gradPick { + display: none; + border: outset 1px #666; + padding: 10px 7px 5px 5px; + overflow: auto; +/* position: relative;*/ +} + +.jGraduate_tabs { + position: relative; + background-color: #EFEFEF; + padding: 0px; + margin: 0px; + margin-bottom: 5px; +} + +div.jGraduate_Swatch { + float: left; + margin: 8px; +} +div.jGraduate_GradContainer { + border: 2px inset #EEE; + background-image: url(../images/map-opacity.png); + background-position: 0px 0px; + height: 256px; + width: 256px; + position: relative; +} + +div.jGraduate_GradContainer div.grad_coord { + background: #000; + border: 1px solid #fff; + border-radius: 5px; + -moz-border-radius: 5px; + width: 10px; + height: 10px; + position: absolute; + margin: -5px -5px; + top: 0; + left: 0; + text-align: center; + font-size: xx-small; + line-height: 10px; + color: #fff; + text-decoration: none; + cursor: pointer; + -moz-user-select: none; + -webkit-user-select: none; +} + +.jGraduate_AlphaArrows { + position: absolute; + margin-top: -10px; + margin-left: 250.5px; +} + +div.jGraduate_Opacity { + border: 2px inset #eee; + margin-top: 14px; + background-color: black; + background-image: url(../images/Maps.png); + background-position: 0px -2816px; + height: 20px; + cursor: ew-resize; +} + +div.jGraduate_StopSlider { +/* border: 2px inset #eee;*/ + margin: 0 0 0 -10px; + width: 276px; + overflow: visible; + background: #efefef; + height: 45px; + cursor: pointer; +} + +div.jGraduate_StopSection { + width: 120px; + text-align: center; +} + + + + +input.jGraduate_Ok, input.jGraduate_Cancel { + display: block; + width: 100px; + margin-left: -4px; + margin-right: -4px; +} +input.jGraduate_Ok { + margin: 9px -4px 5px -4px; +} + +.colorBox { + float: left; + height: 16px; + width: 16px; + border: 1px solid #808080; + cursor: pointer; + margin: 4px 4px 4px 30px; +} + +.colorBox + label { + float: left; + margin-top: 7px; +} + +label.jGraduate_Form_Heading { + position: relative; + top: 10px; + background-color: #EFEFEF; + padding: 2px; + font-weight: bold; + font-size: 13px; +} + +div.jGraduate_Form_Section { + border-style: solid; + border-width: 1px; + border-color: grey; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + padding: 15px 5px 5px 5px; + margin: 5px 2px; + width: 110px; + text-align: center; + overflow: auto; +} + +div.jGraduate_Form_Section label { + padding: 0 2px; +} + +div.jGraduate_StopSection input[type=text], +div.jGraduate_Slider input[type=text] { + width: 33px; +} + +div.jGraduate_LightBox { + position: fixed; + top: 0px; + left: 0px; + right: 0px; + bottom: 0px; + background-color: #000; + opacity: 0.5; + display: none; +} + +div.jGraduate_stopPicker { + position: absolute; + display: none; + background: #E8E8E8; +} + + +.jGraduate_gradPick { + width: 535px; +} + +.jGraduate_gradPick div.jGraduate_OpacField { + + position: absolute; + left: 0; + bottom: 5px; +/* + width: 270px; + + left: 284px; + width: 266px; + height: 200px; + top: 167px; + margin: -3px 3px 0px 4px; +*/ +} + +.jGraduate_gradPick .jGraduate_Form { + float: left; + width: 270px; + position: absolute; + left: 284px; + width: 266px; + height: 200px; + top: 167px; + margin: -3px 3px 0px 10px; +} + +.jGraduate_gradPick .jGraduate_Points { + position: static; + width: 150px; + margin-left: 0; +} + +.jGraduate_SpreadMethod { + position: absolute; + right: 8px; + top: 100px; +} + +.jGraduate_Colorblocks { + display: table; + border-spacing: 0 5px; +} + +.jGraduate_colorblock { + display: table-row; +} + +.jGraduate_Colorblocks .jGraduate_colorblock > * { + display: table-cell; + vertical-align: middle; + margin: 0; + float: none; +} + +.jGraduate_gradPick div.jGraduate_StopSection { + float: left; + width: 133px; + margin-top: -8px; +} + + +.jGraduate_gradPick .jGraduate_Form_Section { + padding-top: 9px; +} + + +.jGraduate_Slider { + text-align: center; + float: left; + width: 100%; +} + +.jGraduate_Slider .jGraduate_Form_Section { + border: none; + width: 250px; + padding: 0 2px; + overflow: visible; +} + +.jGraduate_Slider label { + display: inline-block; + float: left; + line-height: 50px; + padding: 0; +} + +.jGraduate_Slider label.prelabel { + width: 40px; + text-align: left; +} + +.jGraduate_SliderBar { + width: 140px; + float: left; + margin-right: 5px; + border:1px solid #BBB; + height:20px; + margin-top:14px; + margin-left:5px; + position: relative; +} + +div.jGraduate_Slider input { + margin-top: 5px; +} + +div.jGraduate_Slider img { + top: 0; + left: 0; + position: absolute; + margin-top: -10px; + cursor:ew-resize; +} + + +.jGraduate_gradPick .jGraduate_OkCancel { + position: absolute; + top: 39px; + right: 10px; + width: 113px; + +} + +.jGraduate_OpacField { + position: absolute; + right: -10px; + bottom: 0; +} \ No newline at end of file diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/AlphaBar.png b/content/media/2015/03/svg-edit-2.7/jgraduate/images/AlphaBar.png new file mode 100755 index 0000000..2950dae Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/AlphaBar.png differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/Bars.png b/content/media/2015/03/svg-edit-2.7/jgraduate/images/Bars.png new file mode 100755 index 0000000..80eb2bb Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/Bars.png differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/Maps.png b/content/media/2015/03/svg-edit-2.7/jgraduate/images/Maps.png new file mode 100755 index 0000000..853d38c Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/Maps.png differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/NoColor.png b/content/media/2015/03/svg-edit-2.7/jgraduate/images/NoColor.png new file mode 100755 index 0000000..5dc4767 Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/NoColor.png differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/bar-opacity.png b/content/media/2015/03/svg-edit-2.7/jgraduate/images/bar-opacity.png new file mode 100755 index 0000000..e42ad08 Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/bar-opacity.png differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/map-opacity.png b/content/media/2015/03/svg-edit-2.7/jgraduate/images/map-opacity.png new file mode 100755 index 0000000..6756cee Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/map-opacity.png differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/mappoint.gif b/content/media/2015/03/svg-edit-2.7/jgraduate/images/mappoint.gif new file mode 100755 index 0000000..f5f8557 Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/mappoint.gif differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/mappoint_c.png b/content/media/2015/03/svg-edit-2.7/jgraduate/images/mappoint_c.png new file mode 100755 index 0000000..d0a6e1c Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/mappoint_c.png differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/mappoint_f.png b/content/media/2015/03/svg-edit-2.7/jgraduate/images/mappoint_f.png new file mode 100755 index 0000000..563ff87 Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/mappoint_f.png differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/picker.gif b/content/media/2015/03/svg-edit-2.7/jgraduate/images/picker.gif new file mode 100755 index 0000000..374d891 Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/picker.gif differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/preview-opacity.png b/content/media/2015/03/svg-edit-2.7/jgraduate/images/preview-opacity.png new file mode 100755 index 0000000..0dd9a2f Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/preview-opacity.png differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/rangearrows.gif b/content/media/2015/03/svg-edit-2.7/jgraduate/images/rangearrows.gif new file mode 100755 index 0000000..9fe89f4 Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/rangearrows.gif differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/images/rangearrows2.gif b/content/media/2015/03/svg-edit-2.7/jgraduate/images/rangearrows2.gif new file mode 100755 index 0000000..fdeb54a Binary files /dev/null and b/content/media/2015/03/svg-edit-2.7/jgraduate/images/rangearrows2.gif differ diff --git a/content/media/2015/03/svg-edit-2.7/jgraduate/jpicker.js b/content/media/2015/03/svg-edit-2.7/jgraduate/jpicker.js new file mode 100755 index 0000000..683052c --- /dev/null +++ b/content/media/2015/03/svg-edit-2.7/jgraduate/jpicker.js @@ -0,0 +1,2091 @@ +/* + * jPicker 1.1.6 + * + * jQuery Plugin for Photoshop style color picker + * + * Copyright (c) 2010 Christopher T. Tillman + * Digital Magic Productions, Inc. (http://www.digitalmagicpro.com/) + * MIT style license, FREE to use, alter, copy, sell, and especially ENHANCE + * + * Painstakingly ported from John Dyers' excellent work on his own color picker based on the Prototype framework. + * + * John Dyers' website: (http://johndyer.name) + * Color Picker page: (http://johndyer.name/post/2007/09/PhotoShop-like-JavaScript-Color-Picker.aspx) + * + */ +(function($, version) +{ + Math.precision = function(value, precision) + { + if (precision === undefined) precision = 0; + return Math.round(value * Math.pow(10, precision)) / Math.pow(10, precision); + }; + var Slider = // encapsulate slider functionality for the ColorMap and ColorBar - could be useful to use a jQuery UI draggable for this with certain extensions + function(bar, options) + { + var $this = this, // private properties, methods, and events - keep these variables and classes invisible to outside code + arrow = bar.find('img:first'), // the arrow image to drag + minX = 0, + maxX = 100, + rangeX = 100, + minY = 0, + maxY = 100, + rangeY = 100, + x = 0, + y = 0, + offset, + timeout, + changeEvents = new Array(), + fireChangeEvents = + function(context) + { + for (var i = 0; i < changeEvents.length; i++) changeEvents[i].call($this, $this, context); + }, + mouseDown = // bind the mousedown to the bar not the arrow for quick snapping to the clicked location + function(e) + { + var off = bar.offset(); + offset = { l: off.left | 0, t: off.top | 0 }; + clearTimeout(timeout); + timeout = setTimeout( // using setTimeout for visual updates - once the style is updated the browser will re-render internally allowing the next Javascript to run + function() + { + setValuesFromMousePosition.call($this, e); + }, 0); + // Bind mousemove and mouseup event to the document so it responds when dragged of of the bar - we will unbind these when on mouseup to save processing + $(document).bind('mousemove', mouseMove).bind('mouseup', mouseUp); + e.preventDefault(); // don't try to select anything or drag the image to the desktop + }, + mouseMove = // set the values as the mouse moves + function(e) + { + clearTimeout(timeout); + timeout = setTimeout( + function() + { + setValuesFromMousePosition.call($this, e); + }, 0); + e.stopPropagation(); + e.preventDefault(); + return false; + }, + mouseUp = // unbind the document events - they aren't needed when not dragging + function(e) + { + $(document).unbind('mouseup', mouseUp).unbind('mousemove', mouseMove); + e.stopPropagation(); + e.preventDefault(); + return false; + }, + setValuesFromMousePosition = // calculate mouse position and set value within the current range + function(e) + { + var locX = e.pageX - offset.l, + locY = e.pageY - offset.t, + barW = bar.w, // local copies for YUI compressor + barH = bar.h; + // keep the arrow within the bounds of the bar + if (locX < 0) locX = 0; + else if (locX > barW) locX = barW; + if (locY < 0) locY = 0; + else if (locY > barH) locY = barH; + val.call($this, 'xy', { x: ((locX / barW) * rangeX) + minX, y: ((locY / barH) * rangeY) + minY }); + }, + draw = + function() + { + var arrowOffsetX = 0, + arrowOffsetY = 0, + barW = bar.w, + barH = bar.h, + arrowW = arrow.w, + arrowH = arrow.h; + setTimeout( + function() + { + if (rangeX > 0) // range is greater than zero + { + // constrain to bounds + if (x == maxX) arrowOffsetX = barW; + else arrowOffsetX = ((x / rangeX) * barW) | 0; + } + if (rangeY > 0) // range is greater than zero + { + // constrain to bounds + if (y == maxY) arrowOffsetY = barH; + else arrowOffsetY = ((y / rangeY) * barH) | 0; + } + // if arrow width is greater than bar width, center arrow and prevent horizontal dragging + if (arrowW >= barW) arrowOffsetX = (barW >> 1) - (arrowW >> 1); // number >> 1 - superfast bitwise divide by two and truncate (move bits over one bit discarding lowest) + else arrowOffsetX -= arrowW >> 1; + // if arrow height is greater than bar height, center arrow and prevent vertical dragging + if (arrowH >= barH) arrowOffsetY = (barH >> 1) - (arrowH >> 1); + else arrowOffsetY -= arrowH >> 1; + // set the arrow position based on these offsets + arrow.css({ left: arrowOffsetX + 'px', top: arrowOffsetY + 'px' }); + }, 0); + }, + val = + function(name, value, context) + { + var set = value !== undefined; + if (!set) + { + if (name === undefined || name == null) name = 'xy'; + switch (name.toLowerCase()) + { + case 'x': return x; + case 'y': return y; + case 'xy': + default: return { x: x, y: y }; + } + } + if (context != null && context == $this) return; + var changed = false, + newX, + newY; + if (name == null) name = 'xy'; + switch (name.toLowerCase()) + { + case 'x': + newX = value && (value.x && value.x | 0 || value | 0) || 0; + break; + case 'y': + newY = value && (value.y && value.y | 0 || value | 0) || 0; + break; + case 'xy': + default: + newX = value && value.x && value.x | 0 || 0; + newY = value && value.y && value.y | 0 || 0; + break; + } + if (newX != null) + { + if (newX < minX) newX = minX; + else if (newX > maxX) newX = maxX; + if (x != newX) + { + x = newX; + changed = true; + } + } + if (newY != null) + { + if (newY < minY) newY = minY; + else if (newY > maxY) newY = maxY; + if (y != newY) + { + y = newY; + changed = true; + } + } + changed && fireChangeEvents.call($this, context || $this); + }, + range = + function (name, value) + { + var set = value !== undefined; + if (!set) + { + if (name === undefined || name == null) name = 'all'; + switch (name.toLowerCase()) + { + case 'minx': return minX; + case 'maxx': return maxX; + case 'rangex': return { minX: minX, maxX: maxX, rangeX: rangeX }; + case 'miny': return minY; + case 'maxy': return maxY; + case 'rangey': return { minY: minY, maxY: maxY, rangeY: rangeY }; + case 'all': + default: return { minX: minX, maxX: maxX, rangeX: rangeX, minY: minY, maxY: maxY, rangeY: rangeY }; + } + } + var changed = false, + newMinX, + newMaxX, + newMinY, + newMaxY; + if (name == null) name = 'all'; + switch (name.toLowerCase()) + { + case 'minx': + newMinX = value && (value.minX && value.minX | 0 || value | 0) || 0; + break; + case 'maxx': + newMaxX = value && (value.maxX && value.maxX | 0 || value | 0) || 0; + break; + case 'rangex': + newMinX = value && value.minX && value.minX | 0 || 0; + newMaxX = value && value.maxX && value.maxX | 0 || 0; + break; + case 'miny': + newMinY = value && (value.minY && value.minY | 0 || value | 0) || 0; + break; + case 'maxy': + newMaxY = value && (value.maxY && value.maxY | 0 || value | 0) || 0; + break; + case 'rangey': + newMinY = value && value.minY && value.minY | 0 || 0; + newMaxY = value && value.maxY && value.maxY | 0 || 0; + break; + case 'all': + default: + newMinX = value && value.minX && value.minX | 0 || 0; + newMaxX = value && value.maxX && value.maxX | 0 || 0; + newMinY = value && value.minY && value.minY | 0 || 0; + newMaxY = value && value.maxY && value.maxY | 0 || 0; + break; + } + if (newMinX != null && minX != newMinX) + { + minX = newMinX; + rangeX = maxX - minX; + } + if (newMaxX != null && maxX != newMaxX) + { + maxX = newMaxX; + rangeX = maxX - minX; + } + if (newMinY != null && minY != newMinY) + { + minY = newMinY; + rangeY = maxY - minY; + } + if (newMaxY != null && maxY != newMaxY) + { + maxY = newMaxY; + rangeY = maxY - minY; + } + }, + bind = + function (callback) + { + if ($.isFunction(callback)) changeEvents.push(callback); + }, + unbind = + function (callback) + { + if (!$.isFunction(callback)) return; + var i; + while ((i = $.inArray(callback, changeEvents)) != -1) changeEvents.splice(i, 1); + }, + destroy = + function() + { + // unbind all possible events and null objects + $(document).unbind('mouseup', mouseUp).unbind('mousemove', mouseMove); + bar.unbind('mousedown', mouseDown); + bar = null; + arrow = null; + changeEvents = null; + }; + $.extend(true, $this, // public properties, methods, and event bindings - these we need to access from other controls + { + val: val, + range: range, + bind: bind, + unbind: unbind, + destroy: destroy + }); + // initialize this control + arrow.src = options.arrow && options.arrow.image; + arrow.w = options.arrow && options.arrow.width || arrow.width(); + arrow.h = options.arrow && options.arrow.height || arrow.height(); + bar.w = options.map && options.map.width || bar.width(); + bar.h = options.map && options.map.height || bar.height(); + // bind mousedown event + bar.bind('mousedown', mouseDown); + bind.call($this, draw); + }, + ColorValuePicker = // controls for all the input elements for the typing in color values + function(picker, color, bindedHex, alphaPrecision) + { + var $this = this, // private properties and methods + inputs = picker.find('td.Text input'), + red = inputs.eq(3), + green = inputs.eq(4), + blue = inputs.eq(5), + alpha = inputs.length > 7 ? inputs.eq(6) : null, + hue = inputs.eq(0), + saturation = inputs.eq(1), + value = inputs.eq(2), + hex = inputs.eq(inputs.length > 7 ? 7 : 6), + ahex = inputs.length > 7 ? inputs.eq(8) : null, + keyDown = // input box key down - use arrows to alter color + function(e) + { + if (e.target.value == '' && e.target != hex.get(0) && (bindedHex != null && e.target != bindedHex.get(0) || bindedHex == null)) return; + if (!validateKey(e)) return e; + switch (e.target) + { + case red.get(0): + switch (e.keyCode) + { + case 38: + red.val(setValueInRange.call($this, (red.val() << 0) + 1, 0, 255)); + color.val('r', red.val(), e.target); + return false; + case 40: + red.val(setValueInRange.call($this, (red.val() << 0) - 1, 0, 255)); + color.val('r', red.val(), e.target); + return false; + } + break; + case green.get(0): + switch (e.keyCode) + { + case 38: + green.val(setValueInRange.call($this, (green.val() << 0) + 1, 0, 255)); + color.val('g', green.val(), e.target); + return false; + case 40: + green.val(setValueInRange.call($this, (green.val() << 0) - 1, 0, 255)); + color.val('g', green.val(), e.target); + return false; + } + break; + case blue.get(0): + switch (e.keyCode) + { + case 38: + blue.val(setValueInRange.call($this, (blue.val() << 0) + 1, 0, 255)); + color.val('b', blue.val(), e.target); + return false; + case 40: + blue.val(setValueInRange.call($this, (blue.val() << 0) - 1, 0, 255)); + color.val('b', blue.val(), e.target); + return false; + } + break; + case alpha && alpha.get(0): + switch (e.keyCode) + { + case 38: + alpha.val(setValueInRange.call($this, parseFloat(alpha.val()) + 1, 0, 100)); + color.val('a', Math.precision((alpha.val() * 255) / 100, alphaPrecision), e.target); + return false; + case 40: + alpha.val(setValueInRange.call($this, parseFloat(alpha.val()) - 1, 0, 100)); + color.val('a', Math.precision((alpha.val() * 255) / 100, alphaPrecision), e.target); + return false; + } + break; + case hue.get(0): + switch (e.keyCode) + { + case 38: + hue.val(setValueInRange.call($this, (hue.val() << 0) + 1, 0, 360)); + color.val('h', hue.val(), e.target); + return false; + case 40: + hue.val(setValueInRange.call($this, (hue.val() << 0) - 1, 0, 360)); + color.val('h', hue.val(), e.target); + return false; + } + break; + case saturation.get(0): + switch (e.keyCode) + { + case 38: + saturation.val(setValueInRange.call($this, (saturation.val() << 0) + 1, 0, 100)); + color.val('s', saturation.val(), e.target); + return false; + case 40: + saturation.val(setValueInRange.call($this, (saturation.val() << 0) - 1, 0, 100)); + color.val('s', saturation.val(), e.target); + return false; + } + break; + case value.get(0): + switch (e.keyCode) + { + case 38: + value.val(setValueInRange.call($this, (value.val() << 0) + 1, 0, 100)); + color.val('v', value.val(), e.target); + return false; + case 40: + value.val(setValueInRange.call($this, (value.val() << 0) - 1, 0, 100)); + color.val('v', value.val(), e.target); + return false; + } + break; + } + }, + keyUp = // input box key up - validate value and set color + function(e) + { + if (e.target.value == '' && e.target != hex.get(0) && (bindedHex != null && e.target != bindedHex.get(0) || bindedHex == null)) return; + if (!validateKey(e)) return e; + switch (e.target) + { + case red.get(0): + red.val(setValueInRange.call($this, red.val(), 0, 255)); + color.val('r', red.val(), e.target); + break; + case green.get(0): + green.val(setValueInRange.call($this, green.val(), 0, 255)); + color.val('g', green.val(), e.target); + break; + case blue.get(0): + blue.val(setValueInRange.call($this, blue.val(), 0, 255)); + color.val('b', blue.val(), e.target); + break; + case alpha && alpha.get(0): + alpha.val(setValueInRange.call($this, alpha.val(), 0, 100)); + color.val('a', Math.precision((alpha.val() * 255) / 100, alphaPrecision), e.target); + break; + case hue.get(0): + hue.val(setValueInRange.call($this, hue.val(), 0, 360)); + color.val('h', hue.val(), e.target); + break; + case saturation.get(0): + saturation.val(setValueInRange.call($this, saturation.val(), 0, 100)); + color.val('s', saturation.val(), e.target); + break; + case value.get(0): + value.val(setValueInRange.call($this, value.val(), 0, 100)); + color.val('v', value.val(), e.target); + break; + case hex.get(0): + hex.val(hex.val().replace(/[^a-fA-F0-9]/g, '').toLowerCase().substring(0, 6)); + bindedHex && bindedHex.val(hex.val()); + color.val('hex', hex.val() != '' ? hex.val() : null, e.target); + break; + case bindedHex && bindedHex.get(0): + bindedHex.val(bindedHex.val().replace(/[^a-fA-F0-9]/g, '').toLowerCase().substring(0, 6)); + hex.val(bindedHex.val()); + color.val('hex', bindedHex.val() != '' ? bindedHex.val() : null, e.target); + break; + case ahex && ahex.get(0): + ahex.val(ahex.val().replace(/[^a-fA-F0-9]/g, '').toLowerCase().substring(0, 2)); + color.val('a', ahex.val() != null ? parseInt(ahex.val(), 16) : null, e.target); + break; + } + }, + blur = // input box blur - reset to original if value empty + function(e) + { + if (color.val() != null) + { + switch (e.target) + { + case red.get(0): red.val(color.val('r')); break; + case green.get(0): green.val(color.val('g')); break; + case blue.get(0): blue.val(color.val('b')); break; + case alpha && alpha.get(0): alpha.val(Math.precision((color.val('a') * 100) / 255, alphaPrecision)); break; + case hue.get(0): hue.val(color.val('h')); break; + case saturation.get(0): saturation.val(color.val('s')); break; + case value.get(0): value.val(color.val('v')); break; + case hex.get(0): + case bindedHex && bindedHex.get(0): + hex.val(color.val('hex')); + bindedHex && bindedHex.val(color.val('hex')); + break; + case ahex && ahex.get(0): ahex.val(color.val('ahex').substring(6)); break; + } + } + }, + validateKey = // validate key + function(e) + { + switch(e.keyCode) + { + case 9: + case 16: + case 29: + case 37: + case 39: + return false; + case 'c'.charCodeAt(): + case 'v'.charCodeAt(): + if (e.ctrlKey) return false; + } + return true; + }, + setValueInRange = // constrain value within range + function(value, min, max) + { + if (value == '' || isNaN(value)) return min; + if (value > max) return max; + if (value < min) return min; + return value; + }, + colorChanged = + function(ui, context) + { + var all = ui.val('all'); + if (context != red.get(0)) red.val(all != null ? all.r : ''); + if (context != green.get(0)) green.val(all != null ? all.g : ''); + if (context != blue.get(0)) blue.val(all != null ? all.b : ''); + if (alpha && context != alpha.get(0)) alpha.val(all != null ? Math.precision((all.a * 100) / 255, alphaPrecision) : ''); + if (context != hue.get(0)) hue.val(all != null ? all.h : ''); + if (context != saturation.get(0)) saturation.val(all != null ? all.s : ''); + if (context != value.get(0)) value.val(all != null ? all.v : ''); + if (context != hex.get(0) && (bindedHex && context != bindedHex.get(0) || !bindedHex)) hex.val(all != null ? all.hex : ''); + if (bindedHex && context != bindedHex.get(0) && context != hex.get(0)) bindedHex.val(all != null ? all.hex : ''); + if (ahex && context != ahex.get(0)) ahex.val(all != null ? all.ahex.substring(6) : ''); + }, + destroy = + function() + { + // unbind all events and null objects + red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).add(hex).add(bindedHex).add(ahex).unbind('keyup', keyUp).unbind('blur', blur); + red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).unbind('keydown', keyDown); + color.unbind(colorChanged); + red = null; + green = null; + blue = null; + alpha = null; + hue = null; + saturation = null; + value = null; + hex = null; + ahex = null; + }; + $.extend(true, $this, // public properties and methods + { + destroy: destroy + }); + red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).add(hex).add(bindedHex).add(ahex).bind('keyup', keyUp).bind('blur', blur); + red.add(green).add(blue).add(alpha).add(hue).add(saturation).add(value).bind('keydown', keyDown); + color.bind(colorChanged); + }; + $.jPicker = + { + List: [], // array holding references to each active instance of the control + Color: // color object - we will be able to assign by any color space type or retrieve any color space info + // we want this public so we can optionally assign new color objects to initial values using inputs other than a string hex value (also supported) + function(init) + { + var $this = this, + r, + g, + b, + a, + h, + s, + v, + changeEvents = new Array(), + fireChangeEvents = + function(context) + { + for (var i = 0; i < changeEvents.length; i++) changeEvents[i].call($this, $this, context); + }, + val = + function(name, value, context) + { + // Kind of ugly + var set = Boolean(value); + if (set && value.ahex === "") value.ahex = "00000000"; + if (!set) + { + if (name === undefined || name == null || name == '') name = 'all'; + if (r == null) return null; + switch (name.toLowerCase()) + { + case 'ahex': return ColorMethods.rgbaToHex({ r: r, g: g, b: b, a: a }); + case 'hex': return val('ahex').substring(0, 6); + case 'all': return { r: r, g: g, b: b, a: a, h: h, s: s, v: v, hex: val.call($this, 'hex'), ahex: val.call($this, 'ahex') }; + default: + var ret={}; + for (var i = 0; i < name.length; i++) + { + switch (name.charAt(i)) + { + case 'r': + if (name.length == 1) ret = r; + else ret.r = r; + break; + case 'g': + if (name.length == 1) ret = g; + else ret.g = g; + break; + case 'b': + if (name.length == 1) ret = b; + else ret.b = b; + break; + case 'a': + if (name.length == 1) ret = a; + else ret.a = a; + break; + case 'h': + if (name.length == 1) ret = h; + else ret.h = h; + break; + case 's': + if (name.length == 1) ret = s; + else ret.s = s; + break; + case 'v': + if (name.length == 1) ret = v; + else ret.v = v; + break; + } + } + return ret == {} ? val.call($this, 'all') : ret; + break; + } + } + if (context != null && context == $this) return; + var changed = false; + if (name == null) name = ''; + if (value == null) + { + if (r != null) + { + r = null; + changed = true; + } + if (g != null) + { + g = null; + changed = true; + } + if (b != null) + { + b = null; + changed = true; + } + if (a != null) + { + a = null; + changed = true; + } + if (h != null) + { + h = null; + changed = true; + } + if (s != null) + { + s = null; + changed = true; + } + if (v != null) + { + v = null; + changed = true; + } + changed && fireChangeEvents.call($this, context || $this); + return; + } + switch (name.toLowerCase()) + { + case 'ahex': + case 'hex': + var ret = ColorMethods.hexToRgba(value && (value.ahex || value.hex) || value || 'none'); + + val.call($this, 'rgba', { r: ret.r, g: ret.g, b: ret.b, a: name == 'ahex' ? ret.a : a != null ? a : 255 }, context); + break; + default: + if (value && (value.ahex != null || value.hex != null)) + { + val.call($this, 'ahex', value.ahex || value.hex || '00000000', context); + return; + } + var newV = {}, rgb = false, hsv = false; + if (value.r !== undefined && !name.indexOf('r') == -1) name += 'r'; + if (value.g !== undefined && !name.indexOf('g') == -1) name += 'g'; + if (value.b !== undefined && !name.indexOf('b') == -1) name += 'b'; + if (value.a !== undefined && !name.indexOf('a') == -1) name += 'a'; + if (value.h !== undefined && !name.indexOf('h') == -1) name += 'h'; + if (value.s !== undefined && !name.indexOf('s') == -1) name += 's'; + if (value.v !== undefined && !name.indexOf('v') == -1) name += 'v'; + for (var i = 0; i < name.length; i++) + { + switch (name.charAt(i)) + { + case 'r': + if (hsv) continue; + rgb = true; + newV.r = value && value.r && value.r | 0 || value && value | 0 || 0; + if (newV.r < 0) newV.r = 0; + else if (newV.r > 255) newV.r = 255; + if (r != newV.r) + { + r = newV.r; + changed = true; + } + break; + case 'g': + if (hsv) continue; + rgb = true; + newV.g = value && value.g && value.g | 0 || value && value | 0 || 0; + if (newV.g < 0) newV.g = 0; + else if (newV.g > 255) newV.g = 255; + if (g != newV.g) + { + g = newV.g; + changed = true; + } + break; + case 'b': + if (hsv) continue; + rgb = true; + newV.b = value && value.b && value.b | 0 || value && value | 0 || 0; + if (newV.b < 0) newV.b = 0; + else if (newV.b > 255) newV.b = 255; + if (b != newV.b) + { + b = newV.b; + changed = true; + } + break; + case 'a': + newV.a = value && value.a != null ? value.a | 0 : value != null ? value | 0 : 255; + if (newV.a < 0) newV.a = 0; + else if (newV.a > 255) newV.a = 255; + if (a != newV.a) + { + a = newV.a; + changed = true; + } + break; + case 'h': + if (rgb) continue; + hsv = true; + newV.h = value && value.h && value.h | 0 || value && value | 0 || 0; + if (newV.h < 0) newV.h = 0; + else if (newV.h > 360) newV.h = 360; + if (h != newV.h) + { + h = newV.h; + changed = true; + } + break; + case 's': + if (rgb) continue; + hsv = true; + newV.s = value && value.s != null ? value.s | 0 : value != null ? value | 0 : 100; + if (newV.s < 0) newV.s = 0; + else if (newV.s > 100) newV.s = 100; + if (s != newV.s) + { + s = newV.s; + changed = true; + } + break; + case 'v': + if (rgb) continue; + hsv = true; + newV.v = value && value.v != null ? value.v | 0 : value != null ? value | 0 : 100; + if (newV.v < 0) newV.v = 0; + else if (newV.v > 100) newV.v = 100; + if (v != newV.v) + { + v = newV.v; + changed = true; + } + break; + } + } + if (changed) + { + if (rgb) + { + r = r || 0; + g = g || 0; + b = b || 0; + var ret = ColorMethods.rgbToHsv({ r: r, g: g, b: b }); + h = ret.h; + s = ret.s; + v = ret.v; + } + else if (hsv) + { + h = h || 0; + s = s != null ? s : 100; + v = v != null ? v : 100; + var ret = ColorMethods.hsvToRgb({ h: h, s: s, v: v }); + r = ret.r; + g = ret.g; + b = ret.b; + } + a = a != null ? a : 255; + fireChangeEvents.call($this, context || $this); + } + break; + } + }, + bind = + function(callback) + { + if ($.isFunction(callback)) changeEvents.push(callback); + }, + unbind = + function(callback) + { + if (!$.isFunction(callback)) return; + var i; + while ((i = $.inArray(callback, changeEvents)) != -1) changeEvents.splice(i, 1); + }, + destroy = + function() + { + changeEvents = null; + } + $.extend(true, $this, // public properties and methods + { + val: val, + bind: bind, + unbind: unbind, + destroy: destroy + }); + if (init) + { + if (init.ahex != null) val('ahex', init); + else if (init.hex != null) val((init.a != null ? 'a' : '') + 'hex', init.a != null ? { ahex: init.hex + ColorMethods.intToHex(init.a) } : init); + else if (init.r != null && init.g != null && init.b != null) val('rgb' + (init.a != null ? 'a' : ''), init); + else if (init.h != null && init.s != null && init.v != null) val('hsv' + (init.a != null ? 'a' : ''), init); + } + }, + ColorMethods: // color conversion methods - make public to give use to external scripts + { + hexToRgba: + function(hex) + { + if (hex === '' || hex === 'none') return { r: null, g: null, b: null, a: null }; + hex = this.validateHex(hex); + var r = '00', g = '00', b = '00', a = '255'; + if (hex.length == 6) hex += 'ff'; + if (hex.length > 6) + { + r = hex.substring(0, 2); + g = hex.substring(2, 4); + b = hex.substring(4, 6); + a = hex.substring(6, hex.length); + } + else + { + if (hex.length > 4) + { + r = hex.substring(4, hex.length); + hex = hex.substring(0, 4); + } + if (hex.length > 2) + { + g = hex.substring(2, hex.length); + hex = hex.substring(0, 2); + } + if (hex.length > 0) b = hex.substring(0, hex.length); + } + return { r: this.hexToInt(r), g: this.hexToInt(g), b: this.hexToInt(b), a: this.hexToInt(a) }; + }, + validateHex: + function(hex) + { + //if (typeof hex === "object") return ""; + hex = hex.toLowerCase().replace(/[^a-f0-9]/g, ''); + if (hex.length > 8) hex = hex.substring(0, 8); + return hex; + }, + rgbaToHex: + function(rgba) + { + return this.intToHex(rgba.r) + this.intToHex(rgba.g) + this.intToHex(rgba.b) + this.intToHex(rgba.a); + }, + intToHex: + function(dec) + { + var result = (dec | 0).toString(16); + if (result.length == 1) result = ('0' + result); + return result.toLowerCase(); + }, + hexToInt: + function(hex) + { + return parseInt(hex, 16); + }, + rgbToHsv: + function(rgb) + { + var r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255, hsv = { h: 0, s: 0, v: 0 }, min = 0, max = 0, delta; + if (r >= g && r >= b) + { + max = r; + min = g > b ? b : g; + } + else if (g >= b && g >= r) + { + max = g; + min = r > b ? b : r; + } + else + { + max = b; + min = g > r ? r : g; + } + hsv.v = max; + hsv.s = max ? (max - min) / max : 0; + if (!hsv.s) hsv.h = 0; + else + { + delta = max - min; + if (r == max) hsv.h = (g - b) / delta; + else if (g == max) hsv.h = 2 + (b - r) / delta; + else hsv.h = 4 + (r - g) / delta; + hsv.h = parseInt(hsv.h * 60); + if (hsv.h < 0) hsv.h += 360; + } + hsv.s = (hsv.s * 100) | 0; + hsv.v = (hsv.v * 100) | 0; + return hsv; + }, + hsvToRgb: + function(hsv) + { + var rgb = { r: 0, g: 0, b: 0, a: 100 }, h = hsv.h, s = hsv.s, v = hsv.v; + if (s == 0) + { + if (v == 0) rgb.r = rgb.g = rgb.b = 0; + else rgb.r = rgb.g = rgb.b = (v * 255 / 100) | 0; + } + else + { + if (h == 360) h = 0; + h /= 60; + s = s / 100; + v = v / 100; + var i = h | 0, + f = h - i, + p = v * (1 - s), + q = v * (1 - (s * f)), + t = v * (1 - (s * (1 - f))); + switch (i) + { + case 0: + rgb.r = v; + rgb.g = t; + rgb.b = p; + break; + case 1: + rgb.r = q; + rgb.g = v; + rgb.b = p; + break; + case 2: + rgb.r = p; + rgb.g = v; + rgb.b = t; + break; + case 3: + rgb.r = p; + rgb.g = q; + rgb.b = v; + break; + case 4: + rgb.r = t; + rgb.g = p; + rgb.b = v; + break; + case 5: + rgb.r = v; + rgb.g = p; + rgb.b = q; + break; + } + rgb.r = (rgb.r * 255) | 0; + rgb.g = (rgb.g * 255) | 0; + rgb.b = (rgb.b * 255) | 0; + } + return rgb; + } + } + }; + var Color = $.jPicker.Color, List = $.jPicker.List, ColorMethods = $.jPicker.ColorMethods; // local copies for YUI compressor + $.fn.jPicker = + function(options) + { + var $arguments = arguments; + return this.each( + function() + { + var $this = this, settings = $.extend(true, {}, $.fn.jPicker.defaults, options); // local copies for YUI compressor + if ($($this).get(0).nodeName.toLowerCase() == 'input') // Add color picker icon if binding to an input element and bind the events to the input + { + $.extend(true, settings, + { + window: + { + bindToInput: true, + expandable: true, + input: $($this) + } + }); + if($($this).val()=='') + { + settings.color.active = new Color({ hex: null }); + settings.color.current = new Color({ hex: null }); + } + else if (ColorMethods.validateHex($($this).val())) + { + settings.color.active = new Color({ hex: $($this).val(), a: settings.color.active.val('a') }); + settings.color.current = new Color({ hex: $($this).val(), a: settings.color.active.val('a') }); + } + } + if (settings.window.expandable) + $($this).after('    '); + else settings.window.liveUpdate = false; // Basic control binding for inline use - You will need to override the liveCallback or commitCallback function to retrieve results + var isLessThanIE7 = parseFloat(navigator.appVersion.split('MSIE')[1]) < 7 && document.body.filters, // needed to run the AlphaImageLoader function for IE6 + container = null, + colorMapDiv = null, + colorBarDiv = null, + colorMapL1 = null, // different layers of colorMap and colorBar + colorMapL2 = null, + colorMapL3 = null, + colorBarL1 = null, + colorBarL2 = null, + colorBarL3 = null, + colorBarL4 = null, + colorBarL5 = null, + colorBarL6 = null, + colorMap = null, // color maps + colorBar = null, + colorPicker = null, + elementStartX = null, // Used to record the starting css positions for dragging the control + elementStartY = null, + pageStartX = null, // Used to record the mousedown coordinates for dragging the control + pageStartY = null, + activePreview = null, // color boxes above the radio buttons + currentPreview = null, + okButton = null, + cancelButton = null, + grid = null, // preset colors grid + iconColor = null, // iconColor for popup icon + iconAlpha = null, // iconAlpha for popup icon + iconImage = null, // iconImage popup icon + moveBar = null, // drag bar + setColorMode = // set color mode and update visuals for the new color mode + function(colorMode) + { + var active = color.active, // local copies for YUI compressor + clientPath = images.clientPath, + hex = active.val('hex'), + rgbMap, + rgbBar; + settings.color.mode = colorMode; + switch (colorMode) + { + case 'h': + setTimeout( + function() + { + setBG.call($this, colorMapDiv, 'transparent'); + setImgLoc.call($this, colorMapL1, 0); + setAlpha.call($this, colorMapL1, 100); + setImgLoc.call($this, colorMapL2, 260); + setAlpha.call($this, colorMapL2, 100); + setBG.call($this, colorBarDiv, 'transparent'); + setImgLoc.call($this, colorBarL1, 0); + setAlpha.call($this, colorBarL1, 100); + setImgLoc.call($this, colorBarL2, 260); + setAlpha.call($this, colorBarL2, 100); + setImgLoc.call($this, colorBarL3, 260); + setAlpha.call($this, colorBarL3, 100); + setImgLoc.call($this, colorBarL4, 260); + setAlpha.call($this, colorBarL4, 100); + setImgLoc.call($this, colorBarL6, 260); + setAlpha.call($this, colorBarL6, 100); + }, 0); + colorMap.range('all', { minX: 0, maxX: 100, minY: 0, maxY: 100 }); + colorBar.range('rangeY', { minY: 0, maxY: 360 }); + if (active.val('ahex') == null) break; + colorMap.val('xy', { x: active.val('s'), y: 100 - active.val('v') }, colorMap); + colorBar.val('y', 360 - active.val('h'), colorBar); + break; + case 's': + setTimeout( + function() + { + setBG.call($this, colorMapDiv, 'transparent'); + setImgLoc.call($this, colorMapL1, -260); + setImgLoc.call($this, colorMapL2, -520); + setImgLoc.call($this, colorBarL1, -260); + setImgLoc.call($this, colorBarL2, -520); + setImgLoc.call($this, colorBarL6, 260); + setAlpha.call($this, colorBarL6, 100); + }, 0); + colorMap.range('all', { minX: 0, maxX: 360, minY: 0, maxY: 100 }); + colorBar.range('rangeY', { minY: 0, maxY: 100 }); + if (active.val('ahex') == null) break; + colorMap.val('xy', { x: active.val('h'), y: 100 - active.val('v') }, colorMap); + colorBar.val('y', 100 - active.val('s'), colorBar); + break; + case 'v': + setTimeout( + function() + { + setBG.call($this, colorMapDiv, '000000'); + setImgLoc.call($this, colorMapL1, -780); + setImgLoc.call($this, colorMapL2, 260); + setBG.call($this, colorBarDiv, hex); + setImgLoc.call($this, colorBarL1, -520); + setImgLoc.call($this, colorBarL2, 260); + setAlpha.call($this, colorBarL2, 100); + setImgLoc.call($this, colorBarL6, 260); + setAlpha.call($this, colorBarL6, 100); + }, 0); + colorMap.range('all', { minX: 0, maxX: 360, minY: 0, maxY: 100 }); + colorBar.range('rangeY', { minY: 0, maxY: 100 }); + if (active.val('ahex') == null) break; + colorMap.val('xy', { x: active.val('h'), y: 100 - active.val('s') }, colorMap); + colorBar.val('y', 100 - active.val('v'), colorBar); + break; + case 'r': + rgbMap = -1040; + rgbBar = -780; + colorMap.range('all', { minX: 0, maxX: 255, minY: 0, maxY: 255 }); + colorBar.range('rangeY', { minY: 0, maxY: 255 }); + if (active.val('ahex') == null) break; + colorMap.val('xy', { x: active.val('b'), y: 255 - active.val('g') }, colorMap); + colorBar.val('y', 255 - active.val('r'), colorBar); + break; + case 'g': + rgbMap = -1560; + rgbBar = -1820; + colorMap.range('all', { minX: 0, maxX: 255, minY: 0, maxY: 255 }); + colorBar.range('rangeY', { minY: 0, maxY: 255 }); + if (active.val('ahex') == null) break; + colorMap.val('xy', { x: active.val('b'), y: 255 - active.val('r') }, colorMap); + colorBar.val('y', 255 - active.val('g'), colorBar); + break; + case 'b': + rgbMap = -2080; + rgbBar = -2860; + colorMap.range('all', { minX: 0, maxX: 255, minY: 0, maxY: 255 }); + colorBar.range('rangeY', { minY: 0, maxY: 255 }); + if (active.val('ahex') == null) break; + colorMap.val('xy', { x: active.val('r'), y: 255 - active.val('g') }, colorMap); + colorBar.val('y', 255 - active.val('b'), colorBar); + break; + case 'a': + setTimeout( + function() + { + setBG.call($this, colorMapDiv, 'transparent'); + setImgLoc.call($this, colorMapL1, -260); + setImgLoc.call($this, colorMapL2, -520); + setImgLoc.call($this, colorBarL1, 260); + setImgLoc.call($this, colorBarL2, 260); + setAlpha.call($this, colorBarL2, 100); + setImgLoc.call($this, colorBarL6, 0); + setAlpha.call($this, colorBarL6, 100); + }, 0); + colorMap.range('all', { minX: 0, maxX: 360, minY: 0, maxY: 100 }); + colorBar.range('rangeY', { minY: 0, maxY: 255 }); + if (active.val('ahex') == null) break; + colorMap.val('xy', { x: active.val('h'), y: 100 - active.val('v') }, colorMap); + colorBar.val('y', 255 - active.val('a'), colorBar); + break; + default: + throw ('Invalid Mode'); + break; + } + switch (colorMode) + { + case 'h': + break; + case 's': + case 'v': + case 'a': + setTimeout( + function() + { + setAlpha.call($this, colorMapL1, 100); + setAlpha.call($this, colorBarL1, 100); + setImgLoc.call($this, colorBarL3, 260); + setAlpha.call($this, colorBarL3, 100); + setImgLoc.call($this, colorBarL4, 260); + setAlpha.call($this, colorBarL4, 100); + }, 0); + break; + case 'r': + case 'g': + case 'b': + setTimeout( + function() + { + setBG.call($this, colorMapDiv, 'transparent'); + setBG.call($this, colorBarDiv, 'transparent'); + setAlpha.call($this, colorBarL1, 100); + setAlpha.call($this, colorMapL1, 100); + setImgLoc.call($this, colorMapL1, rgbMap); + setImgLoc.call($this, colorMapL2, rgbMap - 260); + setImgLoc.call($this, colorBarL1, rgbBar - 780); + setImgLoc.call($this, colorBarL2, rgbBar - 520); + setImgLoc.call($this, colorBarL3, rgbBar); + setImgLoc.call($this, colorBarL4, rgbBar - 260); + setImgLoc.call($this, colorBarL6, 260); + setAlpha.call($this, colorBarL6, 100); + }, 0); + break; + } + if (active.val('ahex') == null) return; + activeColorChanged.call($this, active); + }, + activeColorChanged = // Update color when user changes text values + function(ui, context) + { + if (context == null || (context != colorBar && context != colorMap)) positionMapAndBarArrows.call($this, ui, context); + setTimeout( + function() + { + updatePreview.call($this, ui); + updateMapVisuals.call($this, ui); + updateBarVisuals.call($this, ui); + }, 0); + }, + mapValueChanged = // user has dragged the ColorMap pointer + function(ui, context) + { + var active = color.active; + if (context != colorMap && active.val() == null) return; + var xy = ui.val('all'); + switch (settings.color.mode) + { + case 'h': + active.val('sv', { s: xy.x, v: 100 - xy.y }, context); + break; + case 's': + case 'a': + active.val('hv', { h: xy.x, v: 100 - xy.y }, context); + break; + case 'v': + active.val('hs', { h: xy.x, s: 100 - xy.y }, context); + break; + case 'r': + active.val('gb', { g: 255 - xy.y, b: xy.x }, context); + break; + case 'g': + active.val('rb', { r: 255 - xy.y, b: xy.x }, context); + break; + case 'b': + active.val('rg', { r: xy.x, g: 255 - xy.y }, context); + break; + } + }, + colorBarValueChanged = // user has dragged the ColorBar slider + function(ui, context) + { + var active = color.active; + if (context != colorBar && active.val() == null) return; + switch (settings.color.mode) + { + case 'h': + active.val('h', { h: 360 - ui.val('y') }, context); + break; + case 's': + active.val('s', { s: 100 - ui.val('y') }, context); + break; + case 'v': + active.val('v', { v: 100 - ui.val('y') }, context); + break; + case 'r': + active.val('r', { r: 255 - ui.val('y') }, context); + break; + case 'g': + active.val('g', { g: 255 - ui.val('y') }, context); + break; + case 'b': + active.val('b', { b: 255 - ui.val('y') }, context); + break; + case 'a': + active.val('a', 255 - ui.val('y'), context); + break; + } + }, + positionMapAndBarArrows = // position map and bar arrows to match current color + function(ui, context) + { + if (context != colorMap) + { + switch (settings.color.mode) + { + case 'h': + var sv = ui.val('sv'); + colorMap.val('xy', { x: sv != null ? sv.s : 100, y: 100 - (sv != null ? sv.v : 100) }, context); + break; + case 's': + case 'a': + var hv = ui.val('hv'); + colorMap.val('xy', { x: hv && hv.h || 0, y: 100 - (hv != null ? hv.v : 100) }, context); + break; + case 'v': + var hs = ui.val('hs'); + colorMap.val('xy', { x: hs && hs.h || 0, y: 100 - (hs != null ? hs.s : 100) }, context); + break; + case 'r': + var bg = ui.val('bg'); + colorMap.val('xy', { x: bg && bg.b || 0, y: 255 - (bg && bg.g || 0) }, context); + break; + case 'g': + var br = ui.val('br'); + colorMap.val('xy', { x: br && br.b || 0, y: 255 - (br && br.r || 0) }, context); + break; + case 'b': + var rg = ui.val('rg'); + colorMap.val('xy', { x: rg && rg.r || 0, y: 255 - (rg && rg.g || 0) }, context); + break; + } + } + if (context != colorBar) + { + switch (settings.color.mode) + { + case 'h': + colorBar.val('y', 360 - (ui.val('h') || 0), context); + break; + case 's': + var s = ui.val('s'); + colorBar.val('y', 100 - (s != null ? s : 100), context); + break; + case 'v': + var v = ui.val('v'); + colorBar.val('y', 100 - (v != null ? v : 100), context); + break; + case 'r': + colorBar.val('y', 255 - (ui.val('r') || 0), context); + break; + case 'g': + colorBar.val('y', 255 - (ui.val('g') || 0), context); + break; + case 'b': + colorBar.val('y', 255 - (ui.val('b') || 0), context); + break; + case 'a': + var a = ui.val('a'); + colorBar.val('y', 255 - (a != null ? a : 255), context); + break; + } + } + }, + updatePreview = + function(ui) + { + try + { + var all = ui.val('all'); + activePreview.css({ backgroundColor: all && '#' + all.hex || 'transparent' }); + setAlpha.call($this, activePreview, all && Math.precision((all.a * 100) / 255, 4) || 0); + } + catch (e) { } + }, + updateMapVisuals = + function(ui) + { + switch (settings.color.mode) + { + case 'h': + setBG.call($this, colorMapDiv, new Color({ h: ui.val('h') || 0, s: 100, v: 100 }).val('hex')); + break; + case 's': + case 'a': + var s = ui.val('s'); + setAlpha.call($this, colorMapL2, 100 - (s != null ? s : 100)); + break; + case 'v': + var v = ui.val('v'); + setAlpha.call($this, colorMapL1, v != null ? v : 100); + break; + case 'r': + setAlpha.call($this, colorMapL2, Math.precision((ui.val('r') || 0) / 255 * 100, 4)); + break; + case 'g': + setAlpha.call($this, colorMapL2, Math.precision((ui.val('g') || 0) / 255 * 100, 4)); + break; + case 'b': + setAlpha.call($this, colorMapL2, Math.precision((ui.val('b') || 0) / 255 * 100)); + break; + } + var a = ui.val('a'); + setAlpha.call($this, colorMapL3, Math.precision(((255 - (a || 0)) * 100) / 255, 4)); + }, + updateBarVisuals = + function(ui) + { + switch (settings.color.mode) + { + case 'h': + var a = ui.val('a'); + setAlpha.call($this, colorBarL5, Math.precision(((255 - (a || 0)) * 100) / 255, 4)); + break; + case 's': + var hva = ui.val('hva'), + saturatedColor = new Color({ h: hva && hva.h || 0, s: 100, v: hva != null ? hva.v : 100 }); + setBG.call($this, colorBarDiv, saturatedColor.val('hex')); + setAlpha.call($this, colorBarL2, 100 - (hva != null ? hva.v : 100)); + setAlpha.call($this, colorBarL5, Math.precision(((255 - (hva && hva.a || 0)) * 100) / 255, 4)); + break; + case 'v': + var hsa = ui.val('hsa'), + valueColor = new Color({ h: hsa && hsa.h || 0, s: hsa != null ? hsa.s : 100, v: 100 }); + setBG.call($this, colorBarDiv, valueColor.val('hex')); + setAlpha.call($this, colorBarL5, Math.precision(((255 - (hsa && hsa.a || 0)) * 100) / 255, 4)); + break; + case 'r': + case 'g': + case 'b': + var hValue = 0, vValue = 0, rgba = ui.val('rgba'); + if (settings.color.mode == 'r') + { + hValue = rgba && rgba.b || 0; + vValue = rgba && rgba.g || 0; + } + else if (settings.color.mode == 'g') + { + hValue = rgba && rgba.b || 0; + vValue = rgba && rgba.r || 0; + } + else if (settings.color.mode == 'b') + { + hValue = rgba && rgba.r || 0; + vValue = rgba && rgba.g || 0; + } + var middle = vValue > hValue ? hValue : vValue; + setAlpha.call($this, colorBarL2, hValue > vValue ? Math.precision(((hValue - vValue) / (255 - vValue)) * 100, 4) : 0); + setAlpha.call($this, colorBarL3, vValue > hValue ? Math.precision(((vValue - hValue) / (255 - hValue)) * 100, 4) : 0); + setAlpha.call($this, colorBarL4, Math.precision((middle / 255) * 100, 4)); + setAlpha.call($this, colorBarL5, Math.precision(((255 - (rgba && rgba.a || 0)) * 100) / 255, 4)); + break; + case 'a': + var a = ui.val('a'); + setBG.call($this, colorBarDiv, ui.val('hex') || '000000'); + setAlpha.call($this, colorBarL5, a != null ? 0 : 100); + setAlpha.call($this, colorBarL6, a != null ? 100 : 0); + break; + } + }, + setBG = + function(el, c) + { + el.css({ backgroundColor: c && c.length == 6 && '#' + c || 'transparent' }); + }, + setImg = + function(img, src) + { + if (isLessThanIE7 && (src.indexOf('AlphaBar.png') != -1 || src.indexOf('Bars.png') != -1 || src.indexOf('Maps.png') != -1)) + { + img.attr('pngSrc', src); + img.css({ backgroundImage: 'none', filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\')' }); + } + else img.css({ backgroundImage: 'url(\'' + src + '\')' }); + }, + setImgLoc = + function(img, y) + { + img.css({ top: y + 'px' }); + }, + setAlpha = + function(obj, alpha) + { + obj.css({ visibility: alpha > 0 ? 'visible' : 'hidden' }); + if (alpha > 0 && alpha < 100) + { + if (isLessThanIE7) + { + var src = obj.attr('pngSrc'); + if (src != null && (src.indexOf('AlphaBar.png') != -1 || src.indexOf('Bars.png') != -1 || src.indexOf('Maps.png') != -1)) + obj.css({ filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\') progid:DXImageTransform.Microsoft.Alpha(opacity=' + alpha + ')' }); + else obj.css({ opacity: Math.precision(alpha / 100, 4) }); + } + else obj.css({ opacity: Math.precision(alpha / 100, 4) }); + } + else if (alpha == 0 || alpha == 100) + { + if (isLessThanIE7) + { + var src = obj.attr('pngSrc'); + if (src != null && (src.indexOf('AlphaBar.png') != -1 || src.indexOf('Bars.png') != -1 || src.indexOf('Maps.png') != -1)) + obj.css({ filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\', sizingMethod=\'scale\')' }); + else obj.css({ opacity: '' }); + } + else obj.css({ opacity: '' }); + } + }, + revertColor = // revert color to original color when opened + function() + { + color.active.val('ahex', color.current.val('ahex')); + }, + commitColor = // commit the color changes + function() + { + color.current.val('ahex', color.active.val('ahex')); + }, + radioClicked = + function(e) + { + $(this).parents('tbody:first').find('input:radio[value!="'+e.target.value+'"]').removeAttr('checked'); + setColorMode.call($this, e.target.value); + }, + currentClicked = + function() + { + revertColor.call($this); + }, + cancelClicked = + function() + { + revertColor.call($this); + settings.window.expandable && hide.call($this); + $.isFunction(cancelCallback) && cancelCallback.call($this, color.active, cancelButton); + }, + okClicked = + function() + { + commitColor.call($this); + settings.window.expandable && hide.call($this); + $.isFunction(commitCallback) && commitCallback.call($this, color.active, okButton); + }, + iconImageClicked = + function() + { + show.call($this); + }, + currentColorChanged = + function(ui, context) + { + var hex = ui.val('hex'); + currentPreview.css({ backgroundColor: hex && '#' + hex || 'transparent' }); + setAlpha.call($this, currentPreview, Math.precision(((ui.val('a') || 0) * 100) / 255, 4)); + }, + expandableColorChanged = + function(ui, context) + { + var hex = ui.val('hex'); + var va = ui.val('va'); + iconColor.css({ backgroundColor: hex && '#' + hex || 'transparent' }); + setAlpha.call($this, iconAlpha, Math.precision(((255 - (va && va.a || 0)) * 100) / 255, 4)); + if (settings.window.bindToInput&&settings.window.updateInputColor) + settings.window.input.css( + { + backgroundColor: hex && '#' + hex || 'transparent', + color: va == null || va.v > 75 ? '#000000' : '#ffffff' + }); + }, + moveBarMouseDown = + function(e) + { + var element = settings.window.element, // local copies for YUI compressor + page = settings.window.page; + elementStartX = parseInt(container.css('left')); + elementStartY = parseInt(container.css('top')); + pageStartX = e.pageX; + pageStartY = e.pageY; + // bind events to document to move window - we will unbind these on mouseup + $(document).bind('mousemove', documentMouseMove).bind('mouseup', documentMouseUp); + e.preventDefault(); // prevent attempted dragging of the column + }, + documentMouseMove = + function(e) + { + container.css({ left: elementStartX - (pageStartX - e.pageX) + 'px', top: elementStartY - (pageStartY - e.pageY) + 'px' }); + if (settings.window.expandable && !$.support.boxModel) container.prev().css({ left: container.css("left"), top: container.css("top") }); + e.stopPropagation(); + e.preventDefault(); + return false; + }, + documentMouseUp = + function(e) + { + $(document).unbind('mousemove', documentMouseMove).unbind('mouseup', documentMouseUp); + e.stopPropagation(); + e.preventDefault(); + return false; + }, + quickPickClicked = + function(e) + { + e.preventDefault(); + e.stopPropagation(); + color.active.val('ahex', $(this).attr('title') || null, e.target); + return false; + }, + commitCallback = $.isFunction($arguments[1]) && $arguments[1] || null, + liveCallback = $.isFunction($arguments[2]) && $arguments[2] || null, + cancelCallback = $.isFunction($arguments[3]) && $arguments[3] || null, + show = + function() + { + color.current.val('ahex', color.active.val('ahex')); + var attachIFrame = function() + { + if (!settings.window.expandable || $.support.boxModel) return; + var table = container.find('table:first'); + container.before('