Want to share your CSS expertise with others? Apply to the MDN Fellowship by April 1! http://mzl.la/MDNFellowship

mozilla

Compare Revisions

Linear-gradient Generator

Change Revisions

Revision 525175:

Revision 525175 by gabriel_ivanica on

Revision 526739:

Revision 526739 by gabriel_ivanica on

Title:
Linear-gradient Generator
Linear-gradient Generator
Slug:
Web/CSS/Tools/Linear-gradient_Generator
Web/CSS/Tools/Linear-gradient_Generator
Tags:
"Tools", "CSS"
Tools, CSS,
Content:

Revision 525175
Revision 526739
n1071 n
t2615var LinearGradientTool=function(){"use strict";function i(e){retut2614 
>rn document.getElementById(e)}function s(e){e.preventDefault()}fu 
>nction o(e,t,n){var r=document.createElement(e);r.className=t;if( 
>n)n.appendChild(r);return r}function u(e,t,n,r){n=n||function(e){ 
>};r=r||function(e){};e.addEventListener("mousedown",function(e){e 
>.preventDefault();n(e);document.addEventListener("mousemove",t);d 
>ocument.addEventListener("mouseup",function i(e){document.removeE 
>ventListener("mousemove",t);document.removeEventListener("mouseup 
>",i);r(e)})});e.addEventListener("click",function(e){e.stopPropag 
>ation()})}function h(e,t){var n=o("div","gradient-axis",null);var 
> r=o("div","gradient-line",n);var i=o("div","rotate-point",n);n.s 
>etAttribute("axisID",t);var s=this.createSVGArrow(t);i.appendChil 
>d(s);this.id=t;this.axis=n;this.unit="%";this.line=r;this.contain 
>er=e;this.lsize=e.clientWidth/2;this.FirstPoint=null;this.ActiveP 
>oint=null;this.gradient="";this.num_points=0;this.size=0;this.ang 
>le=0;this.state=false;this.updateOnResize();u(i,this.updateAxisAn 
>gle.bind(this),this.startRotation.bind(this));e.appendChild(n);r. 
>addEventListener("click",this.placeGradientPoint.bind(this))}var  
>t=180/Math.PI;var n=Math.PI/180;var r={"%":1,px:0};var a=UIColorP 
>icker.Color;var f=UIColorPicker.HSVColor;var l=function(){functio 
>n t(e,t,n,r){var i=0;var s=0;var o=0;var n=typeof n==="function"? 
>n:null;r=r||function(e){};var u=function(r){r.stopPropagation();r 
>.preventDefault();if(r.button!==0)return;i=r.clientX-e.clientWidt 
>h;s=r.clientY-e.clientHeight;document.body.setAttribute("data-res 
>ize",t);document.addEventListener("mousemove",a);document.addEven 
>tListener("mouseup",f)};var a=function(r){if(o>=0)e.style.widt 
>h=r.clientX-i+"px";if(o<=0)e.style.height=r.clientY-s+"px";if( 
>n)n()};var f=function c(e){if(e.button!==0)return;document.body.r 
>emoveAttribute("data-resize",t);document.removeEventListener("mou 
>semove",a);document.removeEventListener("mouseup",c);r()};var l=d 
>ocument.createElement("div");l.className="resize-handle";if(t===" 
>width")o=1;else if(t==="height")o=-1;else t="both";l.className="r 
>esize-handle";l.setAttribute("data-resize",t);l.addEventListener( 
>"mousedown",u);e.appendChild(l)}return{makeResizable:t}}();var c= 
>function(t){var n=document.createElement("div");n.className="grad 
>ient-point";this.position=0;this.node=n;this.Axis=t;this.color=ne 
>w f(0,0,100);this.CSScolor=this.color.getColor();this.CSSposition 
>=0;this.PrevPoint=null;this.NextPoint=null;this.Axis.num_points++ 
>;n.addEventListener("click",this.activate.bind(this));u(n,this.up 
>datePositionM.bind(this),this.startMove.bind(this),this.endMove.b 
>ind(this));t.line.appendChild(n);return this};c.prototype.deleteP 
>oint=function(){this.Axis.line.removeChild(this.node)};c.prototyp 
>e.activate=function(){if(this.Axis.state===false)return;this.Axis 
>.setActivePoint(this);this.node.setAttribute("data-active","true" 
>);UIColorPicker.setColor("picker",this.color);InputSliderManager. 
>setValue("point-position",this.CSSposition);if(this.Axis.num_poin 
>ts>2)p.setDeleteButtonState("active")};c.prototype.deactivate= 
>function(){this.node.removeAttribute("data-active")};c.prototype. 
>startMove=function(t){this.Axis.updateCenterPointPos();this.node. 
>setAttribute("data-active","true");document.body.setAttribute("da 
>ta-dragging","true")};c.prototype.endMove=function(t){this.node.r 
>emoveAttribute("data-active","true");document.body.removeAttribut 
>e("data-dragging")};c.prototype.updatePositionM=function(t){var n 
>=this.Axis;var r=t.clientX-n.centerX;var i=t.clientY-n.centerY;th 
>is.position=(n.Px*r+n.Py*i)/n.Pmod+n.lsize;this.updateCSSPosition 
>();this.Axis.reorderPoint(this);this.Axis.updateGradient();this.u 
>pdateSlider()};c.prototype.setPositionM=function(t,n){var r=this. 
>Axis;var i=t-r.centerX;var s=n-r.centerY;this.position=(r.Px*i+r. 
>Py*s)/r.Pmod+r.lsize;this.updateCSSPosition();this.Axis.reorderPo 
>int(this);this.Axis.updateGradient();this.updateSlider()};c.proto 
>type.updateAbsolutePosition=function(){if(this.Axis.unit="%")this 
>.position=parseFloat((this.CSSposition/100*2*this.Axis.lsize).toF 
>ixed(1));};c.prototype.setPosition=function(t){this.position=t;if 
>(this.Axis.unit==="%")this.position=parseFloat((this.position/100 
>*2*this.Axis.lsize).toFixed(1));this.updateCSSPosition();this.Axi 
>s.reorderPoint(this);this.Axis.updateGradient()};c.prototype.upda 
>teSlider=function(){if(this.Axis.ActivePoint===this&&this 
>.Axis.state===true)InputSliderManager.setValue("point-position",t 
>his.CSSposition,false)};c.prototype.updateColor=function(t){this. 
>color.copy(t);this.CSScolor=t.getColor();this.updateCSSvalue()};c 
>.prototype.updateCSSPosition=function(){this.CSSposition=this.pos 
>ition|0;if(this.Axis.unit==="%")this.CSSposition=parseFloat((100* 
>this.position/(2*this.Axis.lsize)).toFixed(1));this.node.style.le 
>ft=this.CSSposition+this.Axis.unit;this.updateCSSvalue()};c.proto 
>type.updateCSSvalue=function(){this.CSSvalue=this.CSScolor+" "+th 
>is.CSSposition+this.Axis.unit};c.prototype.insertBefore=function( 
>t){this.NextPoint=t;this.PrevPoint=t.PrevPoint;t.PrevPoint=this;i 
>f(this.PrevPoint)this.PrevPoint.NextPoint=this};c.prototype.inser 
>tAfter=function(t){this.NextPoint=t.NextPoint;this.PrevPoint=t;t. 
>NextPoint=this;if(this.NextPoint)this.NextPoint.PrevPoint=this};h 
>.prototype.createSVGArrow=function(t){var n="http://www.w3.org/20 
>00/svg";var r=document.createElementNS(n,"svg");var i=document.cr 
>eateElementNS(n,"path");r.setAttribute("class","gradient-arrow"); 
>r.setAttribute("width","25");r.setAttribute("height","25");i.setA 
>ttribute("fill","#CCC");i.setAttribute("d","M 25,12.5 L 0,0 L 7.5 
>,12.5 L 0,25");r.appendChild(i);return r};h.prototype.placeGradie 
>ntPoint=function(t){this.updateCenterPointPos();var n=new c(this) 
>;n.setPositionM(t.clientX,t.clientY);n.activate();this.attachPoin 
>t(n);this.updateGradient()};h.prototype.newGradientPoint=function 
>(t){var n=new c(this);n.setPosition(t);n.activate();this.attachPo 
>int(n);this.updateGradient()};h.prototype.attachPoint=function(t) 
>{if(this.FirstPoint===null){this.FirstPoint=t;return}var n=this.F 
>irstPoint;while(n.NextPoint){if(t.CSSpositiont.CSSposition&&a 
>mp;t.PrevPoint&&t.PrevPoint.CSSposition1)p.removeAttribut 
>e("data-state")};var N=function(t){n.setAxisAngle(t)};var C=funct 
>ion(t){n.setUnit(t.value)};var k=function(){c=i("add-axis");c.add 
>EventListener("click",function(){if(t.length===4)return;b(0);if(t 
>.length>1)p.removeAttribute("data-state");if(t.length===4)this 
>.setAttribute("data-state","disabled")})};var L=function(){p=i("d 
>elete-axis");p.addEventListener("click",function(){if(this.hasAtt 
>ribute("data-state"))return;if(t.length===1)return;u.removeChild( 
>n.Shortcut);n.deleteAxis();t.splice(x(n.id),1);n=null;H();var e=t 
>.length;for(var r=0;r<4)c.removeattribute("data-state")})};var 
> .textcontent="s;n.children[r].style.height=n.children[r].childre 
>n[1].scrollHeight+"px"};r(0,"")};var" _="function(t){if(v)v.setAt 
>tribute("data-state",t)};var" a="function(t){n.updatePointColor(t 
>)};var" b="function(){a=i("gradient-container");u=i("gradient-axe 
>s");M();L();k();y(18);y(-18);H();UIColorPicker.subscribe("picker" 
>,A);InputSliderManager.subscribe("point-position",O);DropDownMana 
>ger.subscribe("axis-unit",C);SliderManager.subscribe("axis-rotati 
>on",N);l.makeResizable(a,"both",D,P);window.addEventListener("res 
>ize",D)};return{init:B,updateCSSGradient:H,setDeleteButtonState:_ 
>}}();var" d="function(){var" e="[];var" h="function(){var" i="0;i 
><r;i++){e.push(t[i].getCSSGradient())}a.style.background=e.joi 
>n("," m="setTimeout(function(){d.updateOutputCSSCode(e)},500)};va 
>r" n="t.length;for(var" o="function(t){n.updatePointPosition(t)}; 
>var" p="function(){var" pre="" r="0;r<n;r++)t[r].updateOnResiz 
>e()};var" s="function(t){var" v="function(){UIColorPicker.init(); 
>InputSliderManager.init();DropDownManager.init();SliderManager.in 
>it();p.init();d.init()};return{init:v}}();" var=""> 
2615var LinearGradientTool = (function LinearGradientTool() {
2616        'use strict';
2617 
2618        var radian = 180 / Math.PI;
2619        var inv_radian = Math.PI / 180;
2620        var units = {'%': 1, 'px' : 0};
2621 
2622        /*========== DOM Methods ==========*/
2623 
2624        function getElemById(id) {
2625                return document.getElementById(id);
2626        }
2627 
2628        function allowDropEvent(e) {
2629                e.preventDefault();
2630        }
2631 
2632        function createClassElement(tag, className, parent) {
2633                var elem = document.createElement(tag);
2634                elem.className = className;
2635                if (parent) parent.appendChild(elem);
2636                return elem;
2637        };
2638 
2639        function trackMouse(elem, callback, startFunc, endFunc) {
2640                startFunc = startFunc || function(e) {};
2641                endFunc = endFunc || function(e) {};
2642 
2643                elem.addEventListener('mousedown', function(e) {
2644                        e.preventDefault();
2645                        startFunc(e);
2646 
2647                        document.addEventListener('mousemove', ca
 >llback);
2648 
2649                        document.addEventListener('mouseup', func
 >tion up(e) {
2650                                document.removeEventListener('mou
 >semove', callback);
2651                                document.removeEventListener('mou
 >seup', up);
2652                                endFunc(e);
2653                        });
2654                });
2655 
2656                elem.addEventListener('click', function(e) {
2657                        e.stopPropagation();
2658                });
2659        }
2660 
2661        var Color = UIColorPicker.Color;
2662        var HSVColor = UIColorPicker.HSVColor;
2663 
2664        var UIComponent = (function UIComponent() {
2665 
2666                function makeResizable(elem, axis, callback, endF
 >unc) {
2667                        var valueX = 0;
2668                        var valueY = 0;
2669                        var action = 0;
2670                        var callback = typeof callback === "funct
 >ion" ? callback : null;
2671 
2672                        endFunc = endFunc || function(e) {};
2673 
2674                        var resizeStart = function resizeStart(e)
 > {
2675                                e.stopPropagation();
2676                                e.preventDefault();
2677                                if (e.button !== 0)
2678                                        return;
2679 
2680                                valueX = e.clientX - elem.clientW
 >idth;
2681                                valueY = e.clientY - elem.clientH
 >eight;
2682 
2683                                document.body.setAttribute('data-
 >resize', axis);
2684                                document.addEventListener('mousem
 >ove', mouseMove);
2685                                document.addEventListener('mouseu
 >p', resizeEnd);
2686                        };
2687 
2688                        var mouseMove = function mouseMove(e) {
2689                                if (action >= 0)
2690                                        elem.style.width = e.clie
 >ntX - valueX + 'px';
2691                                if (action <= 0)
2692                                        elem.style.height = e.cli
 >entY - valueY + 'px';
2693                                if (callback)
2694                                        callback();
2695                        };
2696 
2697                        var resizeEnd = function resizeEnd(e) {
2698                                if (e.button !== 0)
2699                                        return;
2700 
2701                                document.body.removeAttribute('da
 >ta-resize', axis);
2702                                document.removeEventListener('mou
 >semove', mouseMove);
2703                                document.removeEventListener('mou
 >seup', resizeEnd);
2704                                endFunc();
2705                        };
2706 
2707                        var handle = document.createElement('div'
 >);
2708                        handle.className = 'resize-handle';
2709 
2710                        if (axis === 'width') action = 1;
2711                        else if (axis === 'height') action = -1;
2712                        else axis = 'both';
2713 
2714                        handle.className = 'resize-handle';
2715                        handle.setAttribute('data-resize', axis);
2716                        handle.addEventListener('mousedown', resi
 >zeStart);
2717                        elem.appendChild(handle);
2718                };
2719 
2720                return {
2721                        makeResizable : makeResizable
2722                };
2723        })();
2724 
2725 
2726        /**
2727         * Gradient Point
2728         */
2729        var GradientPoint = function GradientPoint(Axis) {
2730                var point = document.createElement('div');
2731 
2732                point.className = 'gradient-point';
2733 
2734                this.position = 0;
2735                this.node = point;
2736                this.Axis = Axis;
2737                this.color = new HSVColor(0, 0, 100);
2738                this.CSScolor = this.color.getColor();
2739                this.CSSposition = 0;
2740                this.PrevPoint = null;
2741                this.NextPoint = null;
2742 
2743                this.Axis.num_points++;
2744 
2745                point.addEventListener('click', this.activate.bin
 >d(this));
2746                trackMouse(point, this.updatePositionM.bind(this)
 >, this.startMove.bind(this),
2747                        this.endMove.bind(this));
2748 
2749                Axis.line.appendChild(point);
2750                return this;
2751        };
2752 
2753        GradientPoint.prototype.deletePoint = function deletePoin
 >t() {
2754                this.Axis.line.removeChild(this.node);
2755        };
2756 
2757        GradientPoint.prototype.activate = function activate() {
2758                if (this.Axis.state === false)
2759                        return;
2760 
2761                this.Axis.setActivePoint(this);
2762                this.node.setAttribute('data-active', 'true');
2763                UIColorPicker.setColor('picker', this.color);
2764                InputSliderManager.setValue('point-position', thi
 >s.CSSposition);
2765                if (this.Axis.num_points > 2)
2766                        AxesManager.setDeleteButtonState('active'
 >);
2767        };
2768 
2769        GradientPoint.prototype.deactivate = function deactivate(
 >) {
2770                this.node.removeAttribute('data-active');
2771        };
2772 
2773        GradientPoint.prototype.startMove = function startMove(e)
 > {
2774                this.Axis.updateCenterPointPos();
2775                this.node.setAttribute('data-active', 'true');
2776                document.body.setAttribute('data-dragging', 'true
 >');
2777        };
2778 
2779        GradientPoint.prototype.endMove = function endMove(e) {
2780                this.node.removeAttribute('data-active', 'true');
2781                document.body.removeAttribute('data-dragging');
2782        };
2783 
2784        GradientPoint.prototype.updatePositionM = function update
 >PositionM(e) {
2785                var A = this.Axis;
2786                var Qx = e.clientX - A.centerX;
2787                var Qy = e.clientY - A.centerY;
2788                this.position = (A.Px * Qx + A.Py * Qy) / A.Pmod 
 >+ A.lsize;
2789                this.updateCSSPosition();
2790                this.Axis.reorderPoint(this);
2791                this.Axis.updateGradient();
2792                this.updateSlider();
2793        };
2794 
2795        GradientPoint.prototype.setPositionM = function setPositi
 >onM(posX, posY) {
2796                var A = this.Axis;
2797                var Qx = posX - A.centerX;
2798                var Qy = posY - A.centerY;
2799                this.position = (A.Px * Qx + A.Py * Qy) / A.Pmod 
 >+ A.lsize;
2800                this.updateCSSPosition();
2801                this.Axis.reorderPoint(this);
2802                this.Axis.updateGradient();
2803                this.updateSlider();
2804        };
2805 
2806        GradientPoint.prototype.updateAbsolutePosition = function
 > updateAbsolutePosition() {
2807                if (this.Axis.unit ='%')
2808                        this.position = parseFloat(((this.CSSposi
 >tion / 100) * (2 * this.Axis.lsize)).toFixed(1));;
2809        };
2810 
2811        GradientPoint.prototype.setPosition = function setPositio
 >n(pos) {
2812                this.position = pos;
2813                if (this.Axis.unit === '%')
2814                        this.position = parseFloat(((this.positio
 >n / 100) * (2 * this.Axis.lsize)).toFixed(1));;
2815                this.updateCSSPosition();
2816                this.Axis.reorderPoint(this);
2817                this.Axis.updateGradient();
2818        };
2819 
2820        GradientPoint.prototype.updateSlider = function updateSli
 >der() {
2821                if (this.Axis.ActivePoint === this && thi
 >s.Axis.state === true)
2822                        InputSliderManager.setValue('point-positi
 >on', this.CSSposition, false);
2823        };
2824 
2825        GradientPoint.prototype.updateColor = function updateColo
 >r(color) {
2826                this.color.copy(color);
2827                this.CSScolor = color.getColor();
2828                this.updateCSSvalue();
2829        };
2830 
2831        GradientPoint.prototype.updateCSSPosition = function upda
 >teCSSPosition() {
2832                this.CSSposition = this.position | 0;
2833                if (this.Axis.unit === '%')
2834                        this.CSSposition = parseFloat((100 * this
 >.position / (2 * this.Axis.lsize)).toFixed(1));
2835 
2836                this.node.style.left = this.CSSposition + this.Ax
 >is.unit;
2837                this.updateCSSvalue();
2838        };
2839 
2840        GradientPoint.prototype.updateCSSvalue = function updateC
 >SSvalue() {
2841                this.CSSvalue = this.CSScolor + ' ' + this.CSSpos
 >ition + this.Axis.unit;
2842        };
2843 
2844        GradientPoint.prototype.insertBefore = function insertBef
 >ore(point) {
2845                this.NextPoint = point;
2846                this.PrevPoint = point.PrevPoint;
2847                point.PrevPoint = this;
2848                if (this.PrevPoint)
2849                        this.PrevPoint.NextPoint = this;
2850        };
2851 
2852        GradientPoint.prototype.insertAfter = function insertAfte
 >r(point) {
2853                this.NextPoint = point.NextPoint;
2854                this.PrevPoint = point;
2855                point.NextPoint = this;
2856                if (this.NextPoint)
2857                        this.NextPoint.PrevPoint = this;
2858        };
2859 
2860 
2861        /**
2862         * Gradient Axis
2863         */
2864        function GradientAxis(container, id) {
2865                var axis = createClassElement('div', 'gradient-ax
 >is', null);
2866                var line = createClassElement('div', 'gradient-li
 >ne', axis);
2867                var rotate_point = createClassElement('div', 'rot
 >ate-point', axis);
2868 
2869                axis.setAttribute('axisID', id);
2870 
2871                var svg = this.createSVGArrow(id);
2872                rotate_point.appendChild(svg);
2873 
2874                this.id         = id;
2875                this.axis       = axis;
2876                this.unit       = '%';
2877                this.line       = line;
2878                this.container = container;
2879                this.lsize = container.clientWidth / 2;
2880                this.FirstPoint = null;
2881                this.ActivePoint = null;
2882                this.gradient = '';
2883                this.num_points = 0;
2884 
2885                this.size = 0;
2886                this.angle = 0;
2887                this.state = false;
2888                this.updateOnResize();
2889 
2890                trackMouse(rotate_point, this.updateAxisAngle.bin
 >d(this),
2891                                                this.startRotatio
 >n.bind(this));
2892 
2893                container.appendChild(axis);
2894                line.addEventListener('click', this.placeGradient
 >Point.bind(this));
2895        };
2896 
2897 
2898        GradientAxis.prototype.createSVGArrow = function createSV
 >GArrow(id) {
2899                var xmlns = 'http://www.w3.org/2000/svg';
2900                var svg = document.createElementNS(xmlns, 'svg');
2901                var path = document.createElementNS(xmlns, 'path'
 >);
2902 
2903                svg.setAttribute('class', 'gradient-arrow');
2904 
2905                svg.setAttribute('width', '25');
2906                svg.setAttribute('height', '25');
2907 
2908                path.setAttribute('fill', '#CCC');
2909                path.setAttribute('d', 'M 25,12.5 L 0,0 L 7.5,12.
 >5 L 0,25');
2910                svg.appendChild(path);
2911 
2912                return svg;
2913        };
2914 
2915        GradientAxis.prototype.placeGradientPoint = function plac
 >eGradientPoint(e) {
2916                this.updateCenterPointPos();
2917                var point = new GradientPoint(this);
2918                point.setPositionM(e.clientX, e.clientY);
2919                point.activate();
2920                this.attachPoint(point);
2921                this.updateGradient();
2922        };
2923 
2924        GradientAxis.prototype.newGradientPoint = function newGra
 >dientPoint(pos) {
2925                var point = new GradientPoint(this);
2926                point.setPosition(pos);
2927                point.activate();
2928                this.attachPoint(point);
2929                this.updateGradient();
2930        };
2931 
2932        GradientAxis.prototype.attachPoint = function attachPoint
 >(point) {
2933 
2934                // add the first point
2935                if (this.FirstPoint === null) {
2936                        this.FirstPoint = point;
2937                        return;
2938                }
2939 
2940                // insert the point into the list
2941                var p = this.FirstPoint;
2942                while (p.NextPoint) {
2943                        if (point.CSSposition < p.CSSposition)
 > {
2944                                point.insertBefore(p);
2945                                if (point.PrevPoint === null)
2946                                        this.FirstPoint = point;
2947                                return;
2948                        }
2949                        p = p.NextPoint;
2950                };
2951 
2952                // test the last point
2953                if (point.CSSposition < p.CSSposition)
2954                        point.insertBefore(p);
2955                else
2956                        point.insertAfter(p);
2957 
2958                if (point.PrevPoint === null)
2959                        this.FirstPoint = point;
2960 
2961                return;
2962        };
2963 
2964        GradientAxis.prototype.detachPoint = function detachPoint
 >(point) {
2965                if (this.FirstPoint === point)
2966                        this.FirstPoint = point.NextPoint;
2967                if (point.PrevPoint)
2968                        point.PrevPoint.NextPoint = point.NextPoi
 >nt;
2969                if (point.NextPoint)
2970                        point.NextPoint.PrevPoint = point.PrevPoi
 >nt;
2971                point.NextPoint = null;
2972                point.PrevPoint = null;
2973        };
2974 
2975        GradientAxis.prototype.deleteActivePoint = function delet
 >eActivePoint() {
2976                // return if only 2 points left on the axis
2977                if (this.num_points === 2)
2978                        return;
2979 
2980                if (this.ActivePoint) {
2981                        this.ActivePoint.deletePoint();
2982                        this.detachPoint(this.ActivePoint);
2983                        this.updateGradient();
2984                        this.num_points--;
2985                }
2986        };
2987 
2988        GradientAxis.prototype.reorderPoint = function reorderPoi
 >nt(point) {
2989                if (point.NextPoint && point.NextPoint.CS
 >Sposition > point.CSSposition &&
2990                        point.PrevPoint && point.PrevPoin
 >t.CSSposition < point.CSSposition)
2991                        return;
2992                if (point.NextPoint === point.PrevPoint)
2993                        return;
2994 
2995                this.detachPoint(point);
2996                this.attachPoint(point);
2997        };
2998 
2999        GradientAxis.prototype.setActivePoint = function setActiv
 >ePoint(point) {
3000                if (this.ActivePoint)
3001                        this.ActivePoint.deactivate();
3002                this.ActivePoint = point;
3003        };
3004 
3005        GradientAxis.prototype.activate = function activate() {
3006                this.state = true;
3007                this.axis.setAttribute('data-active', this.state)
 >;
3008                InputSliderManager.setUnit('point-position', this
 >.unit, false);
3009                SliderManager.setValue('axis-rotation', this.angl
 >e | 0, false);
3010                DropDownManager.setValue('axis-unit', units[this.
 >unit], false);
3011 
3012                if (this.ActivePoint)
3013                        this.ActivePoint.activate();
3014        };
3015 
3016        GradientAxis.prototype.deactivate = function deactivate()
 > {
3017                this.state = false;
3018                this.axis.removeAttribute('data-active', this.sta
 >te);
3019                if (this.ActivePoint)
3020                        this.ActivePoint.deactivate();
3021        };
3022 
3023        GradientAxis.prototype.deleteAxis = function deleteAxis()
 > {
3024                this.deactivate();
3025                this.container.removeChild(this.axis);
3026        };
3027 
3028        GradientAxis.prototype.updatePointColor = function update
 >PointColor(color) {
3029                if (this.ActivePoint)
3030                        this.ActivePoint.updateColor(color);
3031                this.updateGradient();
3032        };
3033 
3034        GradientAxis.prototype.updatePointPosition = function upd
 >atePointPosition(value) {
3035                if (this.ActivePoint)
3036                        this.ActivePoint.setPosition(value);
3037        };
3038 
3039        GradientAxis.prototype.setUnit = function setUnit(unit) {
3040                this.unit = unit;
3041                this.updateAllPoints();
3042                InputSliderManager.setUnit('point-position', unit
 >, false);
3043 
3044                if (this.ActivePoint)
3045                        this.ActivePoint.updateSlider();
3046 
3047                this.updateGradient();
3048        };
3049 
3050        GradientAxis.prototype.updateAllPoints = function updateA
 >llPoints() {
3051                var p = this.FirstPoint;
3052                while(p) {
3053                        p.updateCSSPosition();
3054                        p = p.NextPoint;
3055                }
3056        };
3057 
3058        /* Axis events */
3059        GradientAxis.prototype.startRotation = function startRota
 >tion(e) {
3060                this.updateCenterPointPos();
3061                this.updateAxisAngle(e);
3062        };
3063 
3064        GradientAxis.prototype.updateOnResize = function updateOn
 >Resize() {
3065                this.updateContainer();
3066                this.updateCenterPointPos();
3067                this.setAxisAngle(this.angle);
3068        };
3069 
3070        GradientAxis.prototype.updateCenterPointPos = function up
 >dateCenterPointPos() {
3071                var pos = this.container.getBoundingClientRect();
3072                this.centerX = (pos.left + pos.right) / 2;
3073                this.centerY = (pos.top + pos.bottom) / 2;
3074        };
3075 
3076        GradientAxis.prototype.updateContainer = function updateC
 >ontainer() {
3077                var W = this.container.clientWidth;
3078                var H = this.container.clientHeight;
3079 
3080                var max_size = Math.sqrt(W * W + H * H) + 50;
3081 
3082                this.axis.style.width = max_size + 'px';
3083                this.axis.style.left = (W - max_size)/2 - 1 + 'px
 >';
3084 
3085                this.mW = W / 2;
3086                this.mH = H / 2;
3087        };
3088 
3089        GradientAxis.prototype.updateAxisAngle = function updateA
 >xisAngle(e) {
3090 
3091                var Px = e.clientX - this.centerX;
3092                var Py = e.clientY - this.centerY;
3093                var deg = -Math.atan2(Py, Px) * radian;
3094                var Pmod = Math.sqrt(Px * Px + Py * Py);
3095                this.lsize = (this.mW * Math.abs(Px) + this.mH * 
 >Math.abs(Py)) / Pmod;
3096 
3097                if (this.state === true)
3098                        SliderManager.setValue('axis-rotation', d
 >eg | 0, false);
3099 
3100                this.angle = deg;
3101                this.updateCSS();
3102                AxesManager.updateCSSGradient();
3103 
3104                this.Px = Px;
3105                this.Py = Py;
3106                this.Pmod = Pmod;
3107        };
3108 
3109        GradientAxis.prototype.setAxisAngle = function setAxisAng
 >le(deg) {
3110                var rad = -deg * inv_radian;
3111                var Px = Math.cos(rad);
3112                var Py = Math.sin(rad);
3113                this.lsize = this.mW * Math.abs(Px) + this.mH * M
 >ath.abs(Py);
3114 
3115                this.angle = deg;
3116                this.updateCSS();
3117                AxesManager.updateCSSGradient();
3118 
3119                this.Px = Px;
3120                this.Py = Py;
3121                this.Pmod = 1;
3122        };
3123 
3124        /* UI Methods - apply CSS */
3125 
3126        GradientAxis.prototype.updateCSS = function updateCSS() {
3127                this.line.style.width = 2 * this.lsize + 'px';
3128                this.axis.style.transform = 'rotate('+ -this.angl
 >e +'deg)';
3129                this.axis.style.webkitTransform = 'rotate('+ -thi
 >s.angle +'deg)';
3130        };
3131 
3132        GradientAxis.prototype.updateGradient = function updateGr
 >adient() {
3133                var p = this.FirstPoint;
3134                if (p === null)
3135                        return;
3136 
3137                this.gradient = p.CSSvalue;
3138                p = p.NextPoint;
3139                while(p) {
3140                        this.gradient += ', ' + p.CSSvalue;
3141                        p = p.NextPoint;
3142                };
3143                AxesManager.updateCSSGradient();
3144        };
3145 
3146        // this is the standard syntax
3147        GradientAxis.prototype.getCSSGradient = function getCSSGr
 >adient() {
3148                return 'linear-gradient('+ (-this.angle + 90 | 0)
 > +'deg, ' + this.gradient + ')';
3149        };
3150 
3151        /**
3152         * AxesManager
3153         */
3154        var AxesManager = (function AxesManager() {
3155 
3156                var lg_axes = [];
3157                var ActiveAxis = null;
3158                var ActiveShortcut = null;
3159                var axes_menu = null;
3160                var gradient_container = null;
3161                var add_axis_btn;
3162                var delete_axis_btn;
3163                var delete_point_btn;
3164                var update_output;
3165                var dragElem;
3166 
3167                var createStartAxis = function createStartAxis(an
 >gle) {
3168 
3169                        if (ActiveAxis)
3170                                ActiveAxis.deactivate();
3171 
3172                        var axisID = getNextAxisID();
3173                        var axis = new GradientAxis(gradient_cont
 >ainer, axisID);
3174                        var color = new HSVColor(210, 90, 90);
3175                        ActiveAxis = axis;
3176 
3177                        axis.activate();
3178                        axis.setAxisAngle(angle);
3179                        axis.newGradientPoint(10);
3180                        axis.updatePointColor(color);
3181 
3182                        color.setAlpha(0.5);
3183                        axis.newGradientPoint(50);
3184                        axis.updatePointColor(color);
3185 
3186                        color.setHue(275);
3187                        axis.newGradientPoint(50);
3188                        axis.updatePointColor(color);
3189 
3190                        color.setAlpha(1);
3191                        axis.newGradientPoint(90);
3192                        axis.updatePointColor(color);
3193 
3194                        UIColorPicker.setColor('picker', color);
3195                        lg_axes.push(axis);
3196 
3197                        axis.Shortcut = createAxisShortcut(axisID
 >);
3198                        axis.activate();
3199                };
3200 
3201                var createAxis = function createAxis(angle) {
3202 
3203                        if (ActiveAxis)
3204                                ActiveAxis.deactivate();
3205 
3206                        var axisID = getNextAxisID();
3207                        var axis = new GradientAxis(gradient_cont
 >ainer, axisID);
3208                        var color = new HSVColor(0, 0, 50);
3209                        ActiveAxis = axis;
3210 
3211                        axis.activate();
3212                        axis.setAxisAngle(angle);
3213                        axis.newGradientPoint(10);
3214                        axis.updatePointColor(color);
3215 
3216                        color.setValue(90);
3217                        axis.newGradientPoint(90);
3218                        axis.updatePointColor(color);
3219 
3220                        UIColorPicker.setColor('picker', color);
3221                        lg_axes.push(axis);
3222 
3223                        axis.Shortcut = createAxisShortcut(axisID
 >);
3224                        axis.activate();
3225                };
3226 
3227                var createAxisShortcut = function createAxisShort
 >cut(axisID) {
3228                        var axis = createClassElement('div', 'axi
 >s', axes_menu);
3229 
3230                        axis.setAttribute('axisID', axisID);
3231                        axis.setAttribute('draggable', 'true');
3232                        axis.style.left = (lg_axes.length - 1) * 
 >60 + 'px';
3233 
3234                        axis.addEventListener('click', function()
 > {
3235                                activateAxisShortcut(axis);
3236                                var axisID = this.getAttribute('a
 >xisID') | 0;
3237                                activateAxis(axisID);
3238                        });
3239 
3240                        axis.addEventListener('dragstart', functi
 >on (e) {
3241                                dragElem = this;
3242                                e.dataTransfer.setData('axisID', 
 >this.getAttribute('axisID'));
3243                        });
3244                        axis.addEventListener('dragover', allowDr
 >opEvent);
3245                        axis.addEventListener('drop', function sw
 >ap(e) {
3246                                if (dragElem === this)
3247                                        return;
3248 
3249                                var from = getOrderID(e.dataTrans
 >fer.getData('axisID'));
3250                                var to = getOrderID(this.getAttri
 >bute('axisID'));
3251 
3252                                var swap = lg_axes[from];
3253                                lg_axes[from] = lg_axes[to];
3254                                lg_axes[to] = swap;
3255 
3256                                var left = dragElem.offsetLeft;
3257                                dragElem.style.left = this.offset
 >Left + 'px';
3258                                this.style.left = left + 'px';
3259 
3260                                updateCSSGradient();
3261                        });
3262 
3263                        activateAxisShortcut(axis);
3264                        return axis;
3265                };
3266 
3267                var activateAxisShortcut = function activateAxisS
 >hortcut(node) {
3268                        if (ActiveShortcut)
3269                                ActiveShortcut.removeAttribute('d
 >ata-state');
3270                        node.setAttribute('data-state', 'active')
 >;
3271                        ActiveShortcut = node;
3272                };
3273 
3274                var getNextAxisID = function getNextAxisID() {
3275                        var ids = [];
3276                        var idx = 0;
3277                        var len = lg_axes.length;
3278 
3279                        for (var i=0; i< lg_axes.length) {
3280                                if (ids[idx] !== true)
3281                                        return idx;
3282                                idx++;
3283                        }
3284 
3285                        return idx;
3286                };
3287 
3288                var getOrderID = function getOrderID(axisID) {
3289                        var len = lg_axes.length;
3290                        for (var i=0; i 1)
3291                                delete_axis_btn.removeAttribute('
 >data-state');
3292                };
3293 
3294                /* Axis functions */
3295 
3296                var updateAxisRotation = function updateAxisRotat
 >ion(value) {
3297                        ActiveAxis.setAxisAngle(value);
3298                };
3299 
3300                var setAxisUnit = function setAxisUnit(obj) {
3301                        ActiveAxis.setUnit(obj.value);
3302                };
3303 
3304                var setAddAxisButton = function setAddAxisButton(
 >) {
3305                        add_axis_btn = getElemById('add-axis');
3306                        add_axis_btn.addEventListener('click', fu
 >nction() {
3307                                if (lg_axes.length === 4)
3308                                        return;
3309 
3310                                createAxis(0);
3311 
3312                                if (lg_axes.length > 1)
3313                                        delete_axis_btn.removeAtt
 >ribute('data-state');
3314                                if (lg_axes.length === 4)
3315                                        this.setAttribute('data-s
 >tate', 'disabled');
3316                        });
3317                };
3318 
3319                var setDeleteAxisButton = function setDeleteAxisB
 >utton() {
3320                        delete_axis_btn = getElemById('delete-axi
 >s');
3321                        delete_axis_btn.addEventListener('click',
 > function () {
3322                                if (this.hasAttribute('data-state
 >'))
3323                                        return;
3324                                if (lg_axes.length === 1)
3325                                        return;
3326 
3327                                axes_menu.removeChild(ActiveAxis.
 >Shortcut);
3328                                ActiveAxis.deleteAxis();
3329                                lg_axes.splice(getOrderID(ActiveA
 >xis.id), 1);
3330 
3331                                ActiveAxis = null;
3332                                updateCSSGradient();
3333 
3334                                var len = lg_axes.length;
3335                                for (var i=0; i< 4)
3336                                        add_axis_btn.removeAttrib
 >ute('data-state');
3337                        });
3338                };
3339 
3340                /* Point methods */
3341 
3342                var updatePointColor = function updatePointColor(
 >color) {
3343                        ActiveAxis.updatePointColor(color);
3344                };
3345 
3346                var updatePointPosition = function updatePointPos
 >ition(color) {
3347                        ActiveAxis.updatePointPosition(color);
3348                };
3349 
3350                var setDeletePointButton = function setDeletePoin
 >tButton() {
3351                        delete_point_btn = getElemById('delete-po
 >int');
3352                        delete_point_btn.addEventListener('click'
 >, function () {
3353                                if (this.getAttribute('data-state
 >') === 'disabled')
3354                                        return;
3355 
3356                                ActiveAxis.deleteActivePoint();
3357                                updateCSSGradient();
3358                                setDeleteButtonState('disabled');
3359                        });
3360                };
3361 
3362                var setDeleteButtonState = function setDeleteButt
 >onState(state) {
3363                        if (delete_point_btn)
3364                                delete_point_btn.setAttribute('da
 >ta-state', state);
3365                };
3366 
3367                /* Container box functions */
3368 
3369                var resizeContainer = function resizeContainer() 
 >{
3370                        var len = lg_axes.length;
3371                        for(var i = 0; i < len; i++)
3372                                lg_axes[i].updateOnResize();
3373                };
3374 
3375                var resizeEnd = function resizeEnd() {
3376                        var len = lg_axes.length;
3377                        for(var i = 0; i < len; i++)
3378                                lg_axes[i].updateAbsolutePosition
 >();
3379                };
3380 
3381                /* General functions */
3382 
3383                var updateCSSGradient = function () {
3384                        var gradient = [];
3385                        var k = 0;
3386                        var len = lg_axes.length;
3387                        for(var i = 0; i < len; i++) {
3388                                gradient.push(lg_axes[i].getCSSGr
 >adient());
3389                        }
3390 
3391                        gradient_container.style.background = gra
 >dient.join(', ');
3392 
3393                        if (update_output)
3394                                window.clearTimeout(update_output
 >);
3395 
3396                        update_output = setTimeout( function() {
3397                                Tool.updateOutputCSSCode(gradient
 >);
3398                        }, 500);
3399                };
3400 
3401                var init = function init() {
3402                        gradient_container = getElemById('gradien
 >t-container');
3403                        axes_menu = getElemById('gradient-axes');
3404 
3405                        setDeletePointButton();
3406                        setDeleteAxisButton();
3407                        setAddAxisButton();
3408 
3409                        createStartAxis(18);
3410                        createStartAxis(-18);
3411 
3412                        updateCSSGradient();
3413 
3414                        UIColorPicker.subscribe('picker', updateP
 >ointColor);
3415                        InputSliderManager.subscribe('point-posit
 >ion', updatePointPosition);
3416 
3417                        DropDownManager.subscribe('axis-unit', se
 >tAxisUnit);
3418                        SliderManager.subscribe('axis-rotation', 
 >updateAxisRotation);
3419 
3420                        UIComponent.makeResizable(gradient_contai
 >ner, 'both', resizeContainer, resizeEnd);
3421                        window.addEventListener('resize', resizeC
 >ontainer);
3422                };
3423 
3424                return {
3425                        init : init,
3426                        updateCSSGradient : updateCSSGradient,
3427                        setDeleteButtonState : setDeleteButtonSta
 >te
3428                };
3429 
3430        })();
3431 
3432 
3433        /**
3434         * Tool
3435         */
3436        var Tool = (function Tool() {
3437 
3438                var container;
3439                var output;
3440 
3441                var setToggleAlphaBackground = function setToggle
 >AlphaBackground() {
3442                        var button = getElemById('canvas-bg');
3443                        var state = true;
3444                        button.addEventListener('click', function
 >() {
3445                                state = !state;
3446                                container.setAttribute('data-alph
 >a', state);
3447                                this.setAttribute('data-alpha', s
 >tate);
3448                        });
3449                };
3450 
3451                var updateOutputCSSCode = function updateOutputCS
 >SCode(gradient) {
3452 
3453                        var updateOutputElem = function updateOut
 >putElem(index, prefix) {
3454                                var code = prefix + gradient.join
 >(',\n ' + prefix) + ';';
3455                                output.children[index].children[1
 >].textContent = code;
3456                                output.children[index].style.heig
 >ht = output.children[index].children[1].scrollHeight + 'px';
3457                        };
3458 
3459                        updateOutputElem(0, '');
3460                };
3461 
3462 
3463                var init = function init() {
3464                        output = getElemById('output');
3465                        container = getElemById('gradient-contain
 >er');
3466 
3467                        setToggleAlphaBackground();
3468                };
3469 
3470                return {
3471                        init : init,
3472                        updateOutputCSSCode: updateOutputCSSCode
3473                };
3474 
3475        })();
3476 
3477        var init = function init() {
3478                UIColorPicker.init();
3479                InputSliderManager.init();
3480                DropDownManager.init();
3481                SliderManager.init();
3482                AxesManager.init();
3483                Tool.init();
3484        };
3485 
3486        return {
3487                init : init
3488        };
3489 
3490})();
3491 
3492 

Back to History