From 046d84280b9e196ac9b695f8e675695eb06ddc4e Mon Sep 17 00:00:00 2001 From: Astor Date: Fri, 1 Aug 2008 02:41:09 +0200 Subject: [PATCH] First commit Plugin complete TODO: code some tests --- MIT-LICENSE | 22 ++ README | 75 ++++++ Rakefile | 22 ++ images/picky_color/body_bg.png | Bin 0 -> 1247 bytes images/picky_color/h.png | Bin 0 -> 609 bytes images/picky_color/h_slider.png | Bin 0 -> 1335 bytes images/picky_color/head_bg.png | Bin 0 -> 1247 bytes images/picky_color/sv.png | Bin 0 -> 15028 bytes images/picky_color/sv_slider.png | Bin 0 -> 1609 bytes init.rb | 4 + install.rb | 10 + javascripts/picky_color.js | 385 +++++++++++++++++++++++++++++++ lib/picky_color.rb | 77 +++++++ stylesheets/picky_color.css | 13 ++ tasks/picky_color_tasks.rake | 4 + test/picky_color_test.rb | 8 + uninstall.rb | 9 + 17 files changed, 629 insertions(+) create mode 100644 MIT-LICENSE create mode 100644 README create mode 100644 Rakefile create mode 100644 images/picky_color/body_bg.png create mode 100644 images/picky_color/h.png create mode 100644 images/picky_color/h_slider.png create mode 100644 images/picky_color/head_bg.png create mode 100644 images/picky_color/sv.png create mode 100644 images/picky_color/sv_slider.png create mode 100644 init.rb create mode 100644 install.rb create mode 100644 javascripts/picky_color.js create mode 100644 lib/picky_color.rb create mode 100644 stylesheets/picky_color.css create mode 100644 tasks/picky_color_tasks.rake create mode 100644 test/picky_color_test.rb create mode 100644 uninstall.rb diff --git a/MIT-LICENSE b/MIT-LICENSE new file mode 100644 index 0000000..b5e2971 --- /dev/null +++ b/MIT-LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2008 Morgan HOTONNIER : Plugin author +Copyright (c) 2007 Brandon Arbini/Sevenwire : Picky-color author + + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README b/README new file mode 100644 index 0000000..37258fd --- /dev/null +++ b/README @@ -0,0 +1,75 @@ +PickyColor +========== + +PickyColor is a Ruby on Rails plugin for the JS color picker based on Prototype/Scriptaculous named... [picky_color][]! (here [is][picky_color_github] his GitHub page) + + +Installation +============ + + ./script/plugin install git://github.com/Astorz/picky-color.git + + +Example usage +============== + +For the case 2 and 3 of this example I will act as if I have to put a color picker for the field color of my model post + +This plugin offer 3 way to use the helper : + +1. Using it like a tag from FormTagHelper. + + <%= picky_color_tag "my_color", "000000" %> + +2. Using it as a FormHelper + + <%= picky_color :post, :color %> + +3. Using it in the Formbuilder + + <%= f.picky_color :color %> + +It is of course possible to add any html option in addition to these parameters as a Hash as last parameter of the methods. They will be applied on the input text field : + + <%= picky_color :post, :color, :class => "my_sexy_class" %> + +In addition to the html options, you have at your disposal 2 custom parameters : **draggable** and **close_text** + +1. *:close_text* takes a string and is the text of the confirm button of the color picker, default is "OK" + +2. *:draggable* takes a boolean and set if the color picker is draggable or not, default is false + +example : + + <%#= picky_color :post, :color, :draggable => true, :close_text => "ColorMe!" %> + + +Authors and credits +=================== + +Author of the plugin : Morgan Hotonnier +Original author of the picker : [Brandon Arbini/Sevenwire][sevenwire] + +Thanks to wildgoose, the author of the rails [calendar_date_select][calendar_date_select_github] plugin, whose code helped me a lot to figure out how to integrate my helper in the built-in formbuilder + +A special thanks to [Gabriel Laskar][gabriel_github_page], who helped me a lot for this plugin, which is my first one. "Merci papi Gabi!" + + + + +Comments and suggestions +------------------------ + +It's my first plugin therefore I'm sure my code is a mess and deserve a lot of improvements, all suggestions are really welcome! + + +[picky_color]: http://code.google.com/p/picky-color/ +[sevenwire]: http://github.com/sevenwire +[picky_color_github]: http://github.com/sevenwire/picky_color/tree/master +[gabriel_github_page]: http://github.com/bibiskuk +[calendar_date_select_github]: http://github.com/timcharper/calendar_date_select/tree/master + + +Copyright (c) 2008 Morgan Hotonnier , released under the MIT license + + \ No newline at end of file diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..19f14d3 --- /dev/null +++ b/Rakefile @@ -0,0 +1,22 @@ +require 'rake' +require 'rake/testtask' +require 'rake/rdoctask' + +desc 'Default: run unit tests.' +task :default => :test + +desc 'Test the picky_color plugin.' +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for the picky_color plugin.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'PickyColor' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('lib/**/*.rb') +end diff --git a/images/picky_color/body_bg.png b/images/picky_color/body_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..0cd4fe9d46a1202fb73e839dfdbf86b82e3f25fe GIT binary patch literal 1247 zcmcIkJ#W)M7&f9pC8$G@7$^*fSr~}VcG9FdIVo+@&>&JuV~K(oay<57=i~kCDVT5dpDw^M6Ry_GSr`vz?H6!9?XTYrCF#uB_&f3C`=j3wyeQVTMT56Q zj|NOyvH1=|RVQFQ9&|!fZe-qktDXehxfoXt7!?lpkmuTLEvt4I>5U|Ez!?Xq+t617liw6Rtw z6tJpeT~7ld9riszqqG-Z9*P|3R9I*Qj-S{S>(U**CyKHhCmN5@<)}YSMF^CF@<|m{2}NF zz0Pf?)t{n+f@Z23SNF4pgFxwjYP0077c1^@s69g9lo00004b3#c}2nYxW zddbVG7wVRUJ4ZXi@?ZDjy9FETeT zFgF9t=?VY<0338hSaefwW^{L9a%BKPWN%_+AVz6&Wp{6KYjYq&Q!|*>Mgsr<0lG;< zK~#90?VC%E!!Qg(>6Fv7tL}RLI}VCT`g70Vg&qoybAbnul#(b;dt9zv#h2x3gk+s! zAV&gnY5?S1&cNhCAcQAtIfJSs$CI20uSkSrW)~w@IYVxYCo#>K6X7E=>Qnk8XF#@? z2Z{GjIYZv-8S+Lz?kay}gepNinQ{$60J)Ny5rAwlp3IK_KFEylKZWGnv~nVhRDwVd z;~xa%ML^yJL?YgPbs!-1FO3$ki(()RSgu$MWXd%JssHT2R04T|$c02W$9QB419Cy0 zpwP02F@hQ zz%fV}I5i5%1^iC|Rf2eeKyo}mD#B&SbuW>=0}IkOA$1UTQ7GrLye zMCYRVLy8u#!Lb$q(g_Gs3FAqtU#?iKekEZ63optOLN3I3Laxquf^<9*VWb%mPh#X^ v(v{Nj5F|z}=Jt!og+LIwVy3X_|8M#Ld%l4>LVxQ(1Wu{nxsYa)PdQV`T4%@|L6OMogGe` zaMC>fE z9Ndfg#!$q70+KZq@Uj94FXg5w+IN5EcQXdGTY#jNMg_ruL|D>N5cJCiENDi~1d*h> z^u8bCT6S5uvG@=tYKlv+V6LK~6M>$hE{HjZKniALHAn&gNFYl=^3<_79oHi;E61h{ zn4C`V;&e{*OJq;T7ASIjNxJ;}6R*4Ci5RG37yqYHUpi_*CrfSNV7{EcU+%V1HH7y_dOG^S4a~-Ijwa$l80l|>v zhm-a?-89eAoCh1@KhwakfHu(Mnk1*E8t7Po;c1rh&>Y=er8j`8^Z;cU(O^v3b?Z(W z;^04qNn*_}ebUI6+aie+%tHmL$i$v8>phc1F0C1gfI_k&WFV!hnE+J}{zH{3LOV`opw>=$;gDWHFzPt)Y4|5Y)M`yfQJHC1#6>ok!-}JNl+V|1aLdVBP zFXuiVx|et^f5;ZirX#=jr={0d&WDp>fBRAWtNqT>{M?U~rDuz!w%ZeT-?ZWM#6Vvn JI@ddX^$(7aVmbf- literal 0 HcmV?d00001 diff --git a/images/picky_color/head_bg.png b/images/picky_color/head_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..d1519f2a494bc79bd0c7f08ecf90a94c3372b8af GIT binary patch literal 1247 zcmcIk%Wl&^6m>;~LQob(>Vm>zFdG)cV>@X=MovnbG&G2`rLjbdSY&EXQY*2?vZsn$ z5JCtLU9w|?#ADBA@Bs+1;{*5u7A&}S(j=`AtU8kCadpnQcg`L8XmkBeCcTiBBq`Ha zt8KwL7w=Q&Vcs}+xd6*-xY96FFrK9B*KoezukD1Abn#OB&3ygw^fv^riq&n=;vF%d z0h5+(zROVE3D|%Ky%1Gfxwqfz=Kwb!k=9hXT3oKvw{{Pg%20A}Z6z;^Q< zvACdS!W7^mcO-Re8WrUeU6an#-enLD7qPsaUv) zT2!FB)I)j^>8c8oPBe|=H7F(-awQF`5!fBFRjZG3!l^9p3E>lr2ZMn!$SFMNVy#pv zVO7Vvo&`iUJn#gKvR-(7C~~Y*W1$r|eqvXwOLzIcD9du3Xgo%jqy9LN7mmyW8*xN^ ztSKrUD+AGhAW0g*1C#T9_=8DWOJ&it0WJ`lpap;hoDpR zCbyl=!4w@7G*i{cVvcBq5q%0Yq8m6iV#=7r_4rPw;^;qy+1A)Ee?RCaZLuxP`pjjX z2*ES$q-VB8Iy`Wxs5ma|GVFU@15bkgtZ!H~JPUZ1c>FGpOCPuLOg0nW&qRJGdX`Ck z-g^HC{vKBvwPo|h8_RCDqc69wwLgA)cE4KBT>kJ%l3GVI(z}iM7XXtQtLwGTEA8ih E0INecbN~PV literal 0 HcmV?d00001 diff --git a/images/picky_color/sv.png b/images/picky_color/sv.png new file mode 100644 index 0000000000000000000000000000000000000000..240b82f4c27cef9616c318064df1dd21b2b88bd4 GIT binary patch literal 15028 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 KMNUMnLSTZQJVaIi literal 0 HcmV?d00001 diff --git a/images/picky_color/sv_slider.png b/images/picky_color/sv_slider.png new file mode 100644 index 0000000000000000000000000000000000000000..03f3d0a5d0b1590870a1e21b4a7825b9f9b0794b GIT binary patch literal 1609 zcmeAS@N?(olHy`uVBq!ia0vp^f*{Pn1|+R>-G2comSQK*5Dp-y;YjHK@;M7UB8wRq zxP?HN@zUM8KR`j564!{5;QX|b^2DN42FH~Aq*MjB%%art{G#k)1?OPn8Q0vHf$Bs- z>YR&G6H7Al^Atidb5j}2^oq@bXnq>!0ns}yePYv5bpoSKp8QB{;0T;&&%T$P<{nWAKG$7NGt z1=O6IT9T+xk(-lOY*k^a1UAzO$OZ}PD=C1Llw{i~K^z_78=&BvUzDm~qGza^Y+!7n zU}C0cWNu_>Zlm6Sjh!2#5Bi3M2Mk92io^naLp=k1xXD0`Hb6lu za75%6h2-bw*kOq?8<0*EMF?9F`cqvJOH%DX;h}3_rfX~vVq{=t0t^_-C?x$5MQGZ6 z^HVa@Dv`7UO)v~GFtjo?wlXw>YDZE8)o!B?3J9ct0f#!sPiW!_1OhB286I8*rA0a5 zXh})dPt8fqP0cGQ28Nj-YM7-YTcza}B047U) zc)El+9Uhf5VIabtCdNYyrKKe=Ef&NuFfg`yx;Tbd^j@88?|&#k;MjbjwtZ7BTxe-* zJ$W(ES)yXP(C&jRoXo=8F6J4`GU4;{lMoj^?ec>~hi$Q;>xITTA)yE<|8ZQ)|<`5vK6*gPTB0f9cMcFtKh|P6n@~mlmpce*arn z&!?dA`LfbiW`<8cYqV$j@QJ!svOGvLn#q3bMn`eo7Bf9AO%blOE=q>)O03ddQUoSG zti0Em8Yw9X8**Bg*nH*FfS< z?i7oF<#+Suv+tehw|rUVtm!=)pF2G36>4|z-=t&B5ED5~w%$*we%9mzSzBi= 1.5.1.1 and Scriptaculous >= 1.7.0. + + Copyright (c) 2007 Brandon Arbini/Sevenwire + http://www.opensource.org/licenses/mit-license.php +*/ + +var PickyColor = Class.create() + +PickyColor.prototype = { + initialize: function(options) { + // Small extension for an ugly IE 6 hack + Prototype.Browser.IE6 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5))==6 + + // Set the options + this.options = Object.extend({ + color: 'FFFFFF', + titleText: 'Choose a color', + closeText: 'close', + colorPickerClass: 'color-picker', + colorPickerHTML: '
#{titleText}
#{closeText}
Saturation and value slider
Hue Slider
', + imageBase: '', + showColor: true, + showHex: true, + showTitle: false, + closable: true, + draggable: true, + startHidden: true, + x: null, + y: null, + zIndex: 100 + }, options || {}) + + // Actions based on options + this.hex = this.options.color + if (this.options.field) this.attachToField() + if (this.options.colorWell) this.attachToColorWell() + + this.createColorPicker() + }, + + + // CALLBACK EVENTS + + event: function(eventName, e) { + if (this.options[eventName]) this.options[eventName](this, e) + }, + + + // COLOR PICKER + + createColorPicker: function() { + this.event('beforeCreate') + + new Insertion.Top(document.body, (new Template(this.options.colorPickerHTML)).evaluate({colorPickerClass:this.options.colorPickerClass, titleText:this.options.titleText, closeText:this.options.closeText, imageBase:this.options.imageBase})) + this.picker = document.body.down(this.colorPickerClass) + this.titleBarElement = $(this.picker).down('.color-picker-title-bar') + this.titleElement = $(this.picker).down('.color-picker-title') + this.closerElement = $(this.picker).down('.color-picker-closer') + this.colorElement = $(this.picker).down('.color-picker-color') + this.hexElement = $(this.picker).down('.color-picker-hex') + this.svElement = $(this.picker).down('.color-picker-sv') + this.svSliderElement = $(this.svElement).down('.color-picker-sv-slider') + this.svElementDimensions = $(this.svElement).getDimensions() + this.hElement = $(this.picker).down('.color-picker-h') + this.hSliderElement = $(this.hElement).down('.color-picker-h-slider') + this.hElementDimensions = $(this.hElement).getDimensions() + + if (this.options.startHidden) this.hide() + this.updatePickerOffsets() + this.updateHex(this.hex) + + $(this.picker).setStyle({ + position: "absolute", + top: (this.options.y || 100)+'px', + left: (this.options.x || 100)+'px', + backgroundImage: "url("+this.options.imageBase+"body_bg.png)", + padding: "15px", + zIndex:this.options.zIndex + }) + $(this.titleBarElement).setStyle({ + backgroundImage: "url("+this.options.imageBase+"head_bg.png)" + }) + $(this.svElement).setStyle({ + backgroundImage: "url("+this.options.imageBase+"sv.png)" + }) + $(this.hElement).setStyle({ + backgroundImage: "url("+this.options.imageBase+"h.png)" + }) + + // UGLY IE 6 HACK! :( + if (Prototype.Browser.IE6) { + $(this.svElement).setStyle({ + backgroundImage: 'none', + filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.options.imageBase+"sv.png', sizingMethod='scale')" + }) + $(this.hSliderElement).setStyle({ + filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.options.imageBase+"h_slider.png', sizingMethod='scale')" + }) + $(this.hSliderElement).down('img').setStyle({ + display: 'none' + }) + $(this.svSliderElement).setStyle({ + filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this.options.imageBase+"sv_slider.png', sizingMethod='scale')" + }) + $(this.svSliderElement).down('img').setStyle({ + display: 'none' + }) + } + + if (!this.options.closable) { + this.closerElement.remove() + } else { + Event.observe(this.closerElement, 'click', function() { + this.hide() + }.bindAsEventListener(this)) + } + if (!this.options.showTitle) this.titleElement.remove() + if (!this.options.showColor) this.colorElement.remove() + if (!this.options.showHex) this.hexElement.remove() + + var snap = function(xMin,xMax,yMin,yMax,x,y,draggable) { + x = Math.min(Math.max(xMin, x), xMax - draggable.element.offsetWidth) + y = Math.min(Math.max(yMin, y), yMax - draggable.element.offsetHeight) + + return [x,y] + } + + this.svSlider = new Draggable(this.svSliderElement, { + snap: function(x,y,draggable) { + return snap(-8,209,-8,209,x,y,draggable) + }, + onStart: function(draggable) { + this.updateSV((draggable.currentDelta()[0]+8)/this.svElementDimensions.width, 1-((draggable.currentDelta()[1]+8)/this.svElementDimensions.height)) + }.bind(this), + change: function(draggable) { + this.updateSV((draggable.currentDelta()[0]+8)/this.svElementDimensions.width, 1-((draggable.currentDelta()[1]+8)/this.svElementDimensions.height)) + }.bind(this), + starteffect: null, + endeffect: null + }) + Event.observe(this.svElement, 'mousedown', function(e) { + var clickX = Event.pointerX(e)-this.svElementOffset[0] + var clickY = Event.pointerY(e)-this.svElementOffset[1] + this.svSliderElement.setStyle({top: clickY-11+'px', left: clickX-11+'px'}) + this.svSlider.initDrag(e) + this.svSlider.startDrag(e) + }.bindAsEventListener(this)) + + this.hSlider = new Draggable(this.hSliderElement, { + constraint:'vertical', + snap: function(x,y,draggable) { + return snap(0,0,-5,207,x,y,draggable) + }, + onStart: function(draggable) { + this.updateH((draggable.currentDelta()[1]+5)/this.hElementDimensions.height) + }.bind(this), + change: function(draggable) { + this.updateH((draggable.currentDelta()[1]+5)/this.hElementDimensions.height) + }.bind(this), + starteffect: null, + endeffect: null + }) + Event.observe(this.hElement, 'mousedown', function(e) { + var clickY = Event.pointerY(e)-this.hElementOffset[1] + this.hSliderElement.setStyle({top: clickY-8+'px'}) + this.hSlider.initDrag(e) + this.hSlider.startDrag(e) + }.bindAsEventListener(this)) + + this.updateHSlider() + this.updateSVSlider() + this.updateSVBackground() + + if (this.options.draggable) this.makeDraggable() + + this.event('afterCreate') + }, + + show: function(e) { + if (e) { + $(this.picker).setStyle({ + top: (this.options.y || Event.pointerY(e)+20)+'px', + left: (this.options.x || Event.pointerX(e))+'px' + }) + } + $(this.picker).show() + this.updatePickerOffsets() + + this.dismissWithESC = function(e) { + if (e.keyCode == Event.KEY_ESC) this.hide() + }.bindAsEventListener(this) + Event.observe(window, 'keypress', this.dismissWithESC) + }, + + hide: function() { + $(this.picker).hide() + if (this.dismissWithESC) Event.stopObserving(window, 'keypress', this.dismissWithESC) + }, + + attachToField: function() { + Event.observe(this.options.field, "change", function(e) { + this.updateHex(Event.element(e).value) + this.updateSVBackground() + this.updateHSlider() + this.updateSVSlider() + }.bindAsEventListener(this)) + }, + + attachToColorWell: function() { + Event.observe(this.options.colorWell, "click", function(e) { + $(this.picker).visible() ? this.hide() : this.show(e) + }.bindAsEventListener(this)) + }, + + makeDraggable: function() { + new Draggable(this.picker, { + onEnd: function(draggable) { + this.updatePickerOffsets() + }.bind(this), + starteffect: null, + endeffect: null + }) + }, + + updatePickerOffsets: function() { + this.hElementOffset = Position.cumulativeOffset(this.hElement) + this.svElementOffset = Position.cumulativeOffset(this.svElement) + }, + + + // INTERFACE UPDATES + + updateHSlider: function() { + this.hSliderElement.setStyle({ + top: (this.hElementDimensions.height*this.HSV.H)-8+'px' + }) + }, + + updateSVSlider: function() { + this.svSliderElement.setStyle({ + top: (this.svElementDimensions.height*(1-this.HSV.V))-8+'px', + left: (this.svElementDimensions.width*this.HSV.S)-8+'px' + }) + }, + + + // UPDATE COLORS + + updateH: function(H) { + this.updateHSV(H, this.HSV.S, this.HSV.V) + this.updateSVBackground() + }, + + updateSVBackground: function() { + Element.setStyle(this.svElement, { + backgroundColor: '#'+this.HSVToHex(this.HSV.H,1,1) + }) + }, + + updateSV: function (S,V) { + this.updateHSV(this.HSV.H, S, V) + }, + + formattedHex: function(hex) { + hex = hex.replace(/[^0-9a-f]/ig,'').toUpperCase() + if (hex.length == 3) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + return hex + }, + + updateHex: function(hex) { + this.hex = this.formattedHex(hex) + this.RGB = this.HexToRGB(hex) + this.HSV = this.HexToHSV(hex) + this.afterColorUpdate() + this.event('afterUpdateHex') + }, + + updateHSV: function(H,S,V) { + this.hex = this.HSVToHex(H,S,V) + this.RGB = this.HexToRGB(this.hex) + this.HSV = { H: H, S: S, V: V } + this.afterColorUpdate() + this.event('afterUpdateHSV') + }, + + updateRGB: function(R,G,B) { + this.hex = this.RGBToHex(R,G,B) + this.RGB = { R: R, G: G, B: B } + this.HSV = this.RGBToHSV(R,G,B) + this.afterColorUpdate() + this.event('afterUpdateRGB') + }, + + afterColorUpdate: function() { + if (this.options.field) $(this.options.field).value = this.hex + if (this.options.showColor) $(this.colorElement).setStyle({ backgroundColor: '#'+this.hex}) + if (this.options.showHex) $(this.hexElement).update('#'+this.hex) + if (this.options.colorWell) $(this.options.colorWell).setStyle({ backgroundColor: '#'+this.hex}) + }, + + + // FUN WITH COLOR + // Brought to you by: + // Brandon Arbini (sevenwire.com), + // EasyRGB (easyrgb.com/math.php), + // Yahoo.util.Color, + // and Ulyses (ColorJack.com) + + HexToRGB: function(hex) { + return { + R: parseInt(hex.substring(0,2), 16), + G: parseInt(hex.substring(2,4), 16), + B: parseInt(hex.substring(4,6), 16) + } + }, + + HexToHSV: function(hex) { + var RGB = this.HexToRGB(hex) + return this.RGBToHSV(RGB.R, RGB.G, RGB.B) + }, + + RGBToHSV: function(R,G,B) { + var H, S, V, var_Min, var_Max, del_Max + + var_Min = Math.min(R,G,B) + var_Max = Math.max(R,G,B) + V = var_Max / 255 + del_Max = var_Max - var_Min + + if (del_Max == 0) return { H: 0, S: 0, V: V } + + S = del_Max / var_Max + + switch (var_Max) { + case R: H = (G - B) / (6 * del_Max); break + case G: H = (B - R) / (6 * del_Max) + 1/3; break + case B: H = (R - G) / (6 * del_Max) + 2/3; break + } + + if (H < 0) H += 1.0; else if (H > 1) H =- 1.0 + + return { H: H, S: S, V: V } + }, + + HSVToHex: function(H,S,V) { + var RGB = this.HSVToRGB(H,S,V) + return this.RGBToHex(RGB.R, RGB.G, RGB.B) + }, + + HSVToRGB: function(H,S,V) { + var V2, VS2, var_i, var_h, rgb_set + + V2 = V * 255 + + var_h = H * 6 + 1.0 + if (var_h >= 6) var_h -= 6.0 + var_i = Math.floor( var_h ) + + VS2 = V2 * S + rgb_set = [V2, V2 - VS2, V2 - VS2] + + if (var_i & 1) rgb_set[1] += VS2 * (var_h - var_i) + else rgb_set[2] += VS2 * (1 - var_h + var_i) + + while (var_i > 1) { rgb_set.unshift(rgb_set.pop()); var_i -= 2 } + + return { R: rgb_set[0], G: rgb_set[1], B: rgb_set[2] } + }, + + RGBToHex: function(R,G,B) { + return this.numToHex(R)+this.numToHex(G)+this.numToHex(B) + }, + + numToHex: function(n) { + n = parseInt(n, 10) + n = Math.min(Math.max(0, isNaN(n) ? 0 : n), 255) + var h = n.toString(16).toUpperCase() + return (h.length < 2) ? "0" + h : h + } +} diff --git a/lib/picky_color.rb b/lib/picky_color.rb new file mode 100644 index 0000000..09ea681 --- /dev/null +++ b/lib/picky_color.rb @@ -0,0 +1,77 @@ +# PickyColor +module PickyColor + module FormHelper + + # Gather the picky_color related options and set them to another hash + # set defaults values if related options aren't set by the user + def picky_color_process_options(options) + picky_options = {} + for key in [:draggable, :close_text, :style_color_well] + picky_options[key] = options.delete(key) if options.has_key?(key) + end + + picky_options[:draggable] ||= false + picky_options[:close_text] ||= 'OK' + + return picky_options + end + + + # include to the output the span and javascript tag needed for the helper + def picky_color_output(input, object_name, method, id, picky_options = {}) + name = method.nil? ? "#{id}" : "#{object_name}_#{method}" + + out = "
" + out << input + out << content_tag(:span, :id => "color_well_#{name}", :class => "color-picker-box") do end + + out << (javascript_tag %{ + color_value = $('#{name}').value + new PickyColor({ + color: color_value, + field: '#{name}', + colorWell: 'color_well_#{name}', + draggable: #{picky_options[:draggable]}, + closeText: '#{picky_options[:close_text]}', + imageBase: '../images/picky_color/' + })}) + + out << "
" + return out + end + + + def picky_color_tag(name, value = nil, options = {}) + picky_options = picky_color_process_options options + options[:id] ||= name + + + input = tag :input, {"type" => "text", + "id" => options[:id], + "name" => name, + "value" => value}.update(options.stringify_keys) + + return picky_color_output(input, name, nil, options[:id], picky_options) + end + + + def picky_color(object, method, options = {}) + obj = options[:object] || instance_variable_get("@#{object}") + picky_options = picky_color_process_options options + + input = ActionView::Helpers::InstanceTag.new(object, method, self, nil, options.delete(:object)) + return picky_color_output input.to_input_field_tag("text", options), object, method, nil, picky_options + end + + end +end + +module ActionView + module Helpers + class FormBuilder + def picky_color(method, options = {}) + @template.picky_color(@object_name, method, options.merge(:object => @object)) + end + end + end +end \ No newline at end of file diff --git a/stylesheets/picky_color.css b/stylesheets/picky_color.css new file mode 100644 index 0000000..f577cb5 --- /dev/null +++ b/stylesheets/picky_color.css @@ -0,0 +1,13 @@ +.color-picker-title-bar, .color-picker-closer { position: absolute; top: -22px; color: white; padding: 5px 15px 3px; } +.color-picker-title-bar { left: 0; width: 245px; height: 15px; } +.color-picker-value { position: absolute; top: -22px; } +.color-picker-color { position: absolute; top: -17px; left: 15px; width: 12px; height: 12px; border: 1px solid #ccc; } +.color-picker-hex { position: absolute; top: -16px; left: 33px; color: white; font-size: 10px; } +.color-picker-closer { right: 0px; cursor: pointer; } +.color-picker img { display: block; margin: 0; padding: 0; border: 0; } +.color-picker div { float: left; } +.color-picker-sv { position: relative; background-repeat: none; margin-right: 20px; width: 200px; height: 200px; } +.color-picker-h { position: relative; background-repeat: none; width: 25px; height: 200px; } +.color-picker-h-slider { position: absolute; left: -14px; top: -5px; width: 44px; height: 12px; } +.color-picker-sv-slider { position: absolute; left: -8px; top: -8px; width: 17px; height: 17px; } +.color-picker-box {width: 50px; height: 20px; margin-left: 10px;position:absolute; cursor: pointer;} diff --git a/tasks/picky_color_tasks.rake b/tasks/picky_color_tasks.rake new file mode 100644 index 0000000..dfd8eaf --- /dev/null +++ b/tasks/picky_color_tasks.rake @@ -0,0 +1,4 @@ +# desc "Explaining what the task does" +# task :picky_color do +# # Task goes here +# end diff --git a/test/picky_color_test.rb b/test/picky_color_test.rb new file mode 100644 index 0000000..e0a86e5 --- /dev/null +++ b/test/picky_color_test.rb @@ -0,0 +1,8 @@ +require 'test/unit' + +class PickyColorTest < Test::Unit::TestCase + # Replace this with your real tests. + def test_this_plugin + flunk + end +end diff --git a/uninstall.rb b/uninstall.rb new file mode 100644 index 0000000..d2b8ded --- /dev/null +++ b/uninstall.rb @@ -0,0 +1,9 @@ +require 'fileutils' + +public_dir = File.join RAILS_ROOT, 'public' + +FileUtils.rm File.join(public_dir, 'javascripts', 'picky-color.js') +FileUtils.rm File.join(public_dir, 'stylesheets', 'picky-color.css') +FileUtils.rm_r File.join(public_dir, 'images', 'picky_color') + +