From daa6df0bb515f4e6ff99c74632dbba9b867c830c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8jberg?= Date: Sat, 12 May 2012 15:29:38 +0200 Subject: [PATCH] Added a way to copy the code to clipboard Use clippy to copy the code to clipboard. This does however add a small delay when the code changes and clippy is recreated. Sadly clippy does not provide a way to dynamically update the clipboard text. --- public/clippy.swf | Bin 0 -> 5380 bytes public/css/app.css | 16 ++++++++------ public/img/clippy.png | Bin 0 -> 561 bytes public/index.html | 9 ++++++-- public/js/lib/app.js | 2 +- public/js/lib/views/arrow_css_view.js | 11 ++++++++-- public/js/lib/views/arrow_preview_view.js | 4 ++-- public/js/spec/views/arrow_css_view_spec.js | 20 +++++++++++++++--- .../js/spec/views/arrow_preview_view_spec.js | 5 +---- public/js/spec_runner.html | 1 + .../vendor/jquery.clippy/jquery.clippy.min.js | 1 + 11 files changed, 48 insertions(+), 21 deletions(-) create mode 100755 public/clippy.swf create mode 100644 public/img/clippy.png create mode 100755 public/js/vendor/jquery.clippy/jquery.clippy.min.js diff --git a/public/clippy.swf b/public/clippy.swf new file mode 100755 index 0000000000000000000000000000000000000000..e46886cd1153122af2f216a6a86cbd816615d54d GIT binary patch literal 5380 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 literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html index 6a947b9..07eeb16 100644 --- a/public/index.html +++ b/public/index.html @@ -52,7 +52,11 @@

Arrow configuration

- + +
+ +
+
@@ -67,7 +71,8 @@

Arrow configuration

- + + diff --git a/public/js/lib/app.js b/public/js/lib/app.js index 7af2769..2d590e9 100644 --- a/public/js/lib/app.js +++ b/public/js/lib/app.js @@ -34,7 +34,7 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {}; this.views = [ new G.ArrowConfigurationView({ model: model, container: $('.configuration') }), new G.ArrowPreviewView({ model: model, container: $('').appendTo('body') }), - new G.ArrowCSSView({ model: model, container: $('.result_code') }), + new G.ArrowCSSView({ model: model, container: $('.css_result') }), ]; }, diff --git a/public/js/lib/views/arrow_css_view.js b/public/js/lib/views/arrow_css_view.js index 2cf8f63..fdcb688 100644 --- a/public/js/lib/views/arrow_css_view.js +++ b/public/js/lib/views/arrow_css_view.js @@ -15,8 +15,10 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {}; init: function (options) { this.container = options.container; - this.model = options.model; + this._codeNode = this.container.find('.code'); + this._copyNode = this.container.find('.copy_code'); + this.model = options.model; this.model.on('change', this._handleChange, this); }, @@ -35,7 +37,12 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {}; @chainable **/ render: function () { - this.container.text( this.model.toCSS() ); + var css = this.model.toCSS(); + + this._codeNode.text( css ); + this._copyNode.text( css ) + .clippy({ transparent: true }); + return this; } diff --git a/public/js/lib/views/arrow_preview_view.js b/public/js/lib/views/arrow_preview_view.js index e42b267..6b31f55 100644 --- a/public/js/lib/views/arrow_preview_view.js +++ b/public/js/lib/views/arrow_preview_view.js @@ -31,11 +31,11 @@ if (!('CSSArrowPlease' in window)) window.CSSArrowPlease = {}; /** @method render - @description borrows the render function from ArrowCSSView + @description renders the css to style the preview @chainable **/ render: function () { - G.ArrowCSSView.prototype.render.call(this); + this.container.text( this.model.toCSS() ); return this; } diff --git a/public/js/spec/views/arrow_css_view_spec.js b/public/js/spec/views/arrow_css_view_spec.js index 8f591a4..74f6bcf 100644 --- a/public/js/spec/views/arrow_css_view_spec.js +++ b/public/js/spec/views/arrow_css_view_spec.js @@ -3,24 +3,38 @@ describe("CSSArrowPlease.ArrowCSSView", function () { var arrow, arrowCSSView, $container; beforeEach(function () { - $container = $('
'); + $container = $('
'); + $code = $container.find('.code'); + $copy = $container.find('.copy_code'); + arrow = new CSSArrowPlease.Arrow(); arrowCSSView = new CSSArrowPlease.ArrowCSSView({ model: arrow, container: $container }); + + spyOn( $copy, 'clippy' ); + + arrowCSSView._codeNode = $code; + arrowCSSView._copyNode = $copy; }); describe('render', function () { + it('returns itself for chainability', function () { expect( arrowCSSView.render() ).toBe( arrowCSSView ); }); it('renders the css when render is called', function () { - expect( $container.text() ).toBe( '' ); + expect( $code.text() ).toBe( '' ); + arrowCSSView.render(); + expect( $code.text() ).toBe( arrow.toCSS() ); + }); + + it('calls clippy() on the copy_code node', function () { arrowCSSView.render(); - expect( $container.text() ).toBe( arrow.toCSS() ); + expect( $copy.clippy ).toHaveBeenCalled(); }); }); diff --git a/public/js/spec/views/arrow_preview_view_spec.js b/public/js/spec/views/arrow_preview_view_spec.js index 6f08d02..0356c46 100644 --- a/public/js/spec/views/arrow_preview_view_spec.js +++ b/public/js/spec/views/arrow_preview_view_spec.js @@ -17,11 +17,8 @@ describe("CSSArrowPlease.ArrowPreviewView", function() { }); it('render delegates to ArrowCSSView.render', function () { - spyOn(CSSArrowPlease.ArrowCSSView.prototype, 'render'); - arrowPreviewView.render(); - - expect(CSSArrowPlease.ArrowCSSView.prototype.render).toHaveBeenCalled(); + expect( $container.text() ).toBe( arrow.toCSS() ); }); }); diff --git a/public/js/spec_runner.html b/public/js/spec_runner.html index c6eb8f2..98163a7 100644 --- a/public/js/spec_runner.html +++ b/public/js/spec_runner.html @@ -8,6 +8,7 @@ + diff --git a/public/js/vendor/jquery.clippy/jquery.clippy.min.js b/public/js/vendor/jquery.clippy/jquery.clippy.min.js new file mode 100755 index 0000000..ed73017 --- /dev/null +++ b/public/js/vendor/jquery.clippy/jquery.clippy.min.js @@ -0,0 +1 @@ +(function(a){a.fn.clippy=function(b){_opts={width:"14",height:"14",color:"#ffffff",clippy_path:"clippy.swf",keep_text:false,transparent:false};b=a.extend(_opts,b);params={movie:b.clippy_path,allowScriptAccess:"always",quality:"high",scale:"noscale"};if(b.transparent&&typeof b.transparent==="string"){params.wmode=b.transparent}else{if(b.transparent&&typeof b.transparent==="boolean"){params.wmode="transparent"}else{params.bgcolor=b.color}}embed_params=a.extend({},params,{width:b.width,height:b.height});embed_params.src=embed_params.movie;delete embed_params.movie;this.each(function(c,f){if(b.text&&b.text!=""){text=b.text}else{if(a(f).data("text")&&a(f).data("text")!=""){text=a(f).data("text")}else{text=a(f).text()}}text=encodeURIComponent(text);params.FlashVars="text="+text;embed_params.FlashVars="text="+text;dom=a("").attr({classid:"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000",width:b.width,height:b.height});embed=a("").attr(embed_params);try{dom.append(embed);a.each(params,function(e,g){dom.prepend(a("").attr({name:e,value:g}))})}catch(d){dom=embed}if(b.keep_text){a(f).html(dom).append(decodeURIComponent(text))}else{a(f).html(dom)}})}})(jQuery); \ No newline at end of file