short 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/README.md +9 -0
- data/Rakefile +3 -0
- data/bin/shortener +115 -0
- data/config.ru +2 -0
- data/lib/shortener/client.rb +69 -0
- data/lib/shortener/configuration.rb +76 -0
- data/lib/shortener/server/Gemfile +6 -0
- data/lib/shortener/server/Gemfile.lock +23 -0
- data/lib/shortener/server/config.ru.template +2 -0
- data/lib/shortener/server/public/delete-icon.png +0 -0
- data/lib/shortener/server/public/flash/Jplayer.swf +0 -0
- data/lib/shortener/server/public/flash/clippy.swf +0 -0
- data/lib/shortener/server/public/flash/swfupload.swf +0 -0
- data/lib/shortener/server/public/images/XPButtonUploadText_61x22.png +0 -0
- data/lib/shortener/server/public/jquery-swfupload-min.js +1 -0
- data/lib/shortener/server/public/jquery-swfupload.js +64 -0
- data/lib/shortener/server/public/jquery.jplayer.min.js +97 -0
- data/lib/shortener/server/public/jquery.min.js +18 -0
- data/lib/shortener/server/public/patched.bootstrap.min.css +370 -0
- data/lib/shortener/server/public/site.js +36 -0
- data/lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.css +623 -0
- data/lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.jpg +0 -0
- data/lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.seeking.gif +0 -0
- data/lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.video.play.png +0 -0
- data/lib/shortener/server/public/swfupload.js +980 -0
- data/lib/shortener/server/views/add.haml +22 -0
- data/lib/shortener/server/views/display.haml +5 -0
- data/lib/shortener/server/views/index.haml +25 -0
- data/lib/shortener/server/views/layout.haml +21 -0
- data/lib/shortener/server/views/s3/audio.haml +75 -0
- data/lib/shortener/server/views/s3/image.haml +27 -0
- data/lib/shortener/server/views/s3/layout.haml +23 -0
- data/lib/shortener/server/views/s3/video.haml +71 -0
- data/lib/shortener/server/views/upload.haml +130 -0
- data/lib/shortener/server.rb +346 -0
- data/lib/shortener/version.rb +6 -0
- data/lib/shortener.rb +9 -0
- data/tasks/heroku.rake +46 -0
- data/test/test_client.rb +26 -0
- data/test/test_configuration.rb +23 -0
- data/test/test_server.rb +0 -0
- metadata +102 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
#shortener.row(style="margin-top: 40px;")
|
2
|
+
%form{:id => 'add-form',:name => "shortener", :action => "/add", :method => "post", :class => 'offset3 form'}
|
3
|
+
%label{:for => "shortener[url]"} Url to Shorten:
|
4
|
+
%input{:type => "text", :name => "shortener[url]", :class => "text"}
|
5
|
+
%input{:type => "submit", :value => "Shorten", :class => "btn primary"}
|
6
|
+
%a{:onClick => '$(".advanced").fadeIn();'} Show Advanced Options
|
7
|
+
%br
|
8
|
+
%label{:for => 'shortener[expire]', :class => 'advanced'} Time till Expired:
|
9
|
+
%input{:type => 'text', :name => 'shortener[expire]', :class => 'text advanced'}
|
10
|
+
%br
|
11
|
+
%label{:for => 'shortener[max-clicks]', :class => 'advanced'} Max Clicks:
|
12
|
+
%input{:type => 'text', :name => 'shortener[max-clicks]', :class => 'text advanced'}
|
13
|
+
%br
|
14
|
+
%label{:for => 'shortener[desired-short]', :class => 'advanced'} Desired Short:
|
15
|
+
%input{:type => 'text', :name => 'shortener[desired-short]', :class => 'text advanced'}
|
16
|
+
%br
|
17
|
+
%label{:for => 'shortener[allow-override]', :class => 'advanced'} Allow Random Override:
|
18
|
+
%input{:type => 'checkbox', :name => 'shortener[allow-override]', :class => 'text advanced', :value => 'true'}
|
19
|
+
:javascript
|
20
|
+
$(function(){
|
21
|
+
$('.advanced').hide();
|
22
|
+
})
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#shorterner-index
|
2
|
+
%table
|
3
|
+
%thead
|
4
|
+
%tr
|
5
|
+
%th Shortened
|
6
|
+
%th Full Url
|
7
|
+
%th Set Count
|
8
|
+
%th Click Count
|
9
|
+
%th TTL
|
10
|
+
%th Max Clicks
|
11
|
+
%tbody
|
12
|
+
- @shortens.each do |short|
|
13
|
+
%tr
|
14
|
+
%td= short['shortened']
|
15
|
+
%td
|
16
|
+
%a{href: short['url']}= short['url'][0..50] + ((short['url'].length > 50) ? '...' : '')
|
17
|
+
%td= short['set-count']
|
18
|
+
%td= short['click-count'] || 0
|
19
|
+
%td= ttl_display(short['expire'])
|
20
|
+
%td= short['max-clicks'] || "∞"
|
21
|
+
%td
|
22
|
+
%a{href: "/delete/#{short['shortened']}", class: 'delete-button'}
|
23
|
+
%img{src: 'delete-icon.png', alt: 'delete!', width: '16px', height: '16px'}
|
24
|
+
%td= clippy("#{base_url}/#{short['shortened']}")
|
25
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title Shortener
|
5
|
+
%link{rel: 'stylesheet', type: 'text/css', href: '/patched.bootstrap.min.css'}
|
6
|
+
%script{src: '/jquery.min.js', type: 'text/javascript'}
|
7
|
+
%script{src: 'site.js', type: 'text/javascript'}
|
8
|
+
%body{:'padding-top' => '60px'}
|
9
|
+
|
10
|
+
%div.topbar
|
11
|
+
%div.topbar-inner
|
12
|
+
%div.container
|
13
|
+
%a{class: 'brand', href: "/"} Shortener
|
14
|
+
%ul.nav
|
15
|
+
%li
|
16
|
+
%a{href: '/index'} Index
|
17
|
+
%li
|
18
|
+
%a{href: '/add'} Add
|
19
|
+
|
20
|
+
#main.container(style="margin-top: 40px;")
|
21
|
+
= yield
|
@@ -0,0 +1,75 @@
|
|
1
|
+
%link{href: "skin/blue.monday/jplayer.blue.monday.css", rel: 'stylesheet', type: 'text/css'}
|
2
|
+
%script{src: 'jquery.jplayer.min.js', type: 'text/javascript'}
|
3
|
+
|
4
|
+
%br
|
5
|
+
%br
|
6
|
+
.row
|
7
|
+
#jquery_jplayer_1.jp-jplayer.center
|
8
|
+
#jp_container_1.jp-audio.center
|
9
|
+
.jp-type-single
|
10
|
+
.jp-gui.jp-interface
|
11
|
+
%ul.jp-controls
|
12
|
+
%li
|
13
|
+
%a.jp-play{:href => "javascript:;", :tabindex => "1"} play
|
14
|
+
%li
|
15
|
+
%a.jp-pause{:href => "javascript:;", :tabindex => "1"} pause
|
16
|
+
%li
|
17
|
+
%a.jp-stop{:href => "javascript:;", :tabindex => "1"} stop
|
18
|
+
%li
|
19
|
+
%a.jp-mute{:href => "javascript:;", :tabindex => "1", :title => "mute"} mute
|
20
|
+
%li
|
21
|
+
%a.jp-unmute{:href => "javascript:;", :tabindex => "1", :title => "unmute"} unmute
|
22
|
+
%li
|
23
|
+
%a.jp-volume-max{:href => "javascript:;", :tabindex => "1", :title => "max volume"} max volume
|
24
|
+
.jp-progress
|
25
|
+
.jp-seek-bar
|
26
|
+
.jp-play-bar
|
27
|
+
.jp-volume-bar
|
28
|
+
.jp-volume-bar-value
|
29
|
+
.jp-time-holder
|
30
|
+
.jp-current-time
|
31
|
+
.jp-duration
|
32
|
+
%ul.jp-toggles
|
33
|
+
%li
|
34
|
+
%a.jp-repeat{:href => "javascript:;", :tabindex => "1", :title => "repeat"} repeat
|
35
|
+
%li
|
36
|
+
%a.jp-repeat-off{:href => "javascript:;", :tabindex => "1", :title => "repeat off"} repeat off
|
37
|
+
.jp-title
|
38
|
+
%ul
|
39
|
+
%li= @short['name']
|
40
|
+
%li= @short['description']
|
41
|
+
.jp-no-solution
|
42
|
+
%span Update Required
|
43
|
+
To play the media you will need to either update your browser to a recent version or update your
|
44
|
+
= succeed "." do
|
45
|
+
%a{:href => "http://get.adobe.com/flashplayer/", :target => "_blank"} Flash plugin
|
46
|
+
|
47
|
+
:javascript
|
48
|
+
|
49
|
+
$("#jquery_jplayer_1").jPlayer({
|
50
|
+
ready: function () {
|
51
|
+
$(this).jPlayer("setMedia", {
|
52
|
+
#{@short['extension']}: "#{@short['url']}",
|
53
|
+
});
|
54
|
+
},
|
55
|
+
play: function() { // To avoid both jPlayers playing together.
|
56
|
+
$(this).jPlayer("pauseOthers");
|
57
|
+
},
|
58
|
+
repeat: function(event) { // Override the default jPlayer repeat event handler
|
59
|
+
if(event.jPlayer.options.loop) {
|
60
|
+
$(this).unbind(".jPlayerRepeat").unbind(".jPlayerNext");
|
61
|
+
$(this).bind($.jPlayer.event.ended + ".jPlayer.jPlayerRepeat", function() {
|
62
|
+
$(this).jPlayer("play");
|
63
|
+
});
|
64
|
+
} else {
|
65
|
+
$(this).unbind(".jPlayerRepeat").unbind(".jPlayerNext");
|
66
|
+
$(this).bind($.jPlayer.event.ended + ".jPlayer.jPlayerNext", function() {
|
67
|
+
$("#jquery_jplayer_2").jPlayer("play", 0);
|
68
|
+
});
|
69
|
+
}
|
70
|
+
},
|
71
|
+
swfPath: "js",
|
72
|
+
supplied: "#{@short['extension']}",
|
73
|
+
wmode: "window"
|
74
|
+
});
|
75
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
%br
|
2
|
+
%br
|
3
|
+
:css
|
4
|
+
img {
|
5
|
+
max-width: 100%;
|
6
|
+
}
|
7
|
+
|
8
|
+
.row
|
9
|
+
%a.center{href: @short['url']}
|
10
|
+
%img{src: @short['url']}
|
11
|
+
|
12
|
+
.row
|
13
|
+
%p
|
14
|
+
%b Name:
|
15
|
+
= @short['name']
|
16
|
+
|
17
|
+
.row
|
18
|
+
%p
|
19
|
+
%b Descrtiption:
|
20
|
+
%br
|
21
|
+
= @short['description']
|
22
|
+
|
23
|
+
:css
|
24
|
+
.center {
|
25
|
+
margin: 0 auto;
|
26
|
+
padding: 0;
|
27
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title Shortener
|
5
|
+
%link{rel: 'stylesheet', type: 'text/css', href: '/patched.bootstrap.min.css'}
|
6
|
+
%script{src: 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js', type: 'text/javascript'}
|
7
|
+
%script{src: 'site.js', type: 'text/javascript'}
|
8
|
+
%body{:'padding-top' => '60px'}
|
9
|
+
|
10
|
+
#main.container(style="margin-top: 40px;")
|
11
|
+
= yield
|
12
|
+
.row
|
13
|
+
%a.center{href: "#{@short['url']}"} Download
|
14
|
+
:css
|
15
|
+
body {
|
16
|
+
background-color: #787171;
|
17
|
+
}
|
18
|
+
|
19
|
+
.center {
|
20
|
+
margin: 0 auto;
|
21
|
+
padding: 0;
|
22
|
+
}
|
23
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
%link{href: "skin/blue.monday/jplayer.blue.monday.css", rel: 'stylesheet', type: 'text/css'}
|
2
|
+
%script{src: 'jquery.jplayer.min.js', type: 'text/javascript'}
|
3
|
+
|
4
|
+
#jp_container_1.jp-video.jp-video-360p.center
|
5
|
+
.jp-type-single
|
6
|
+
#jquery_jplayer_1.jp-jplayer
|
7
|
+
.jp-gui
|
8
|
+
.jp-video-play
|
9
|
+
%a.jp-video-play-icon{:href => "javascript:;", :tabindex => "1"} play
|
10
|
+
.jp-interface
|
11
|
+
.jp-progress
|
12
|
+
.jp-seek-bar
|
13
|
+
.jp-play-bar
|
14
|
+
.jp-current-time
|
15
|
+
.jp-duration
|
16
|
+
.jp-controls-holder
|
17
|
+
%ul.jp-controls
|
18
|
+
%li
|
19
|
+
%a.jp-play{:href => "javascript:;", :tabindex => "1"} play
|
20
|
+
%li
|
21
|
+
%a.jp-pause{:href => "javascript:;", :tabindex => "1"} pause
|
22
|
+
%li
|
23
|
+
%a.jp-stop{:href => "javascript:;", :tabindex => "1"} stop
|
24
|
+
%li
|
25
|
+
%a.jp-mute{:href => "javascript:;", :tabindex => "1", :title => "mute"} mute
|
26
|
+
%li
|
27
|
+
%a.jp-unmute{:href => "javascript:;", :tabindex => "1", :title => "unmute"} unmute
|
28
|
+
%li
|
29
|
+
%a.jp-volume-max{:href => "javascript:;", :tabindex => "1", :title => "max volume"} max volume
|
30
|
+
.jp-volume-bar
|
31
|
+
.jp-volume-bar-value
|
32
|
+
%ul.jp-toggles
|
33
|
+
%li
|
34
|
+
%a.jp-full-screen{:href => "javascript:;", :tabindex => "1", :title => "full screen"} full screen
|
35
|
+
%li
|
36
|
+
%a.jp-restore-screen{:href => "javascript:;", :tabindex => "1", :title => "restore screen"} restore screen
|
37
|
+
%li
|
38
|
+
%a.jp-repeat{:href => "javascript:;", :tabindex => "1", :title => "repeat"} repeat
|
39
|
+
%li
|
40
|
+
%a.jp-repeat-off{:href => "javascript:;", :tabindex => "1", :title => "repeat off"} repeat off
|
41
|
+
.jp-title
|
42
|
+
%ul
|
43
|
+
%li= @short['name']
|
44
|
+
%li= @short['description']
|
45
|
+
.jp-no-solution
|
46
|
+
%span Update Required
|
47
|
+
To play the media you will need to either update your browser to a recent version or update your
|
48
|
+
= succeed "." do
|
49
|
+
%a{:href => "http://get.adobe.com/flashplayer/", :target => "_blank"} Flash plugin
|
50
|
+
|
51
|
+
|
52
|
+
:javascript
|
53
|
+
|
54
|
+
$("#jquery_jplayer_1").jPlayer({
|
55
|
+
ready: function () {
|
56
|
+
$(this).jPlayer("setMedia", { #{@short['extension']}: "#{@short['url']}" });
|
57
|
+
},
|
58
|
+
swfPath: "js",
|
59
|
+
supplied: "#{@short['extension']}",
|
60
|
+
size: {
|
61
|
+
width: "640px",
|
62
|
+
height: "360px",
|
63
|
+
cssClass: "jp-video-360p"
|
64
|
+
}
|
65
|
+
});
|
66
|
+
|
67
|
+
:css
|
68
|
+
.center {
|
69
|
+
margin: 0 auto;
|
70
|
+
padding: 0;
|
71
|
+
}
|
@@ -0,0 +1,130 @@
|
|
1
|
+
%script{src: "swfupload.js"}
|
2
|
+
%script{src: "jquery-swfupload-min.js"}
|
3
|
+
:erb
|
4
|
+
<script>
|
5
|
+
$(function(){
|
6
|
+
$('#swfupload-control').swfupload({
|
7
|
+
// Backend Settings
|
8
|
+
upload_url: "<%= @upload_url %>", // Relative to the SWF file (or you can use absolute paths)
|
9
|
+
http_success : [ 200, 201, 204 ], // FOR AWS
|
10
|
+
|
11
|
+
// File Upload Settings
|
12
|
+
file_size_limit : "102400", // 100MB
|
13
|
+
file_types : "*.*",
|
14
|
+
file_types_description : "All Files",
|
15
|
+
file_upload_limit : "10",
|
16
|
+
file_queue_limit : "0",
|
17
|
+
file_post_name : "file", // FOR AWS
|
18
|
+
|
19
|
+
// Button settings
|
20
|
+
button_image_url : "/images/XPButtonUploadText_61x22.png",
|
21
|
+
button_placeholder_id : "span-button-placeholder",
|
22
|
+
button_width: 61,
|
23
|
+
button_height: 22,
|
24
|
+
|
25
|
+
// Flash Settings
|
26
|
+
flash_url : "/flash/swfupload.swf",
|
27
|
+
//debug: true,
|
28
|
+
post_params: <%= @post.to_json %> // FOR AWS
|
29
|
+
|
30
|
+
})
|
31
|
+
.bind('fileQueued', function(event, file){
|
32
|
+
// start the upload since it's queued
|
33
|
+
//$(this).swfupload('startUpload');
|
34
|
+
$(this).swfupload('setButtonDisabled', true);
|
35
|
+
$('#file-name-placeholder').text(file.name);
|
36
|
+
})
|
37
|
+
.bind('fileQueueError', function(event, file, errorCode, message){
|
38
|
+
//$('#log').append('<li>File queue error - '+message+'</li>');
|
39
|
+
//$(this).show();
|
40
|
+
})
|
41
|
+
.bind('uploadStart', function(event, file){
|
42
|
+
$('#progressbar').show();
|
43
|
+
})
|
44
|
+
.bind('uploadProgress', function(event, file, bytesLoaded){
|
45
|
+
var avg = bytesLoaded / file.size * 100;
|
46
|
+
//$('#log').append('<li>Upload progress - '+bytesLoaded+ ' ' + avg + '</li>');
|
47
|
+
$('#progressbar .bar').css('width', avg + '%' );
|
48
|
+
})
|
49
|
+
.bind('uploadSuccess', function(event, file, serverData){
|
50
|
+
//$('#log').append('<li>Upload success - '+file.name+'</li>');
|
51
|
+
})
|
52
|
+
.bind('uploadComplete', function(event, file){
|
53
|
+
//$('#log').append('<li>Upload complete - '+file.name+'</li>');
|
54
|
+
$('#progressbar .active').removeClass('active');
|
55
|
+
|
56
|
+
var values = $('#upload-form').serialize();
|
57
|
+
values += '&shortener%5bfile_name%5d=' + file.name;
|
58
|
+
// Change this callback function to suite your needs
|
59
|
+
// $.ajax({
|
60
|
+
// type: "POST",
|
61
|
+
// url: '/upload',
|
62
|
+
// data: "name=" + file.name,
|
63
|
+
// async: false,
|
64
|
+
// });
|
65
|
+
$.post('/upload', values, function(data){
|
66
|
+
$('#shortener-display').text(data.url)
|
67
|
+
.removeClass('hide');
|
68
|
+
});
|
69
|
+
|
70
|
+
// upload has completed, lets try the next one in the queue
|
71
|
+
$(this).swfupload('startUpload');
|
72
|
+
})
|
73
|
+
.bind('uploadError', function(event, file, errorCode, message){
|
74
|
+
//$('#log').append('<li>Upload error - '+message+'</li>');
|
75
|
+
});
|
76
|
+
|
77
|
+
});
|
78
|
+
</script>
|
79
|
+
|
80
|
+
.row
|
81
|
+
#progressbar.span8{style: 'display:none;'}
|
82
|
+
.progress.danger.active.striped
|
83
|
+
.bar{style: "width: 0%"}
|
84
|
+
|
85
|
+
.row
|
86
|
+
%div.offset1{:id=> "swfupload-control"}
|
87
|
+
%ol{:id=> "log"}
|
88
|
+
%span{:id=> "span-button-placeholder"}
|
89
|
+
%span{id: 'file-name-placeholder'}
|
90
|
+
%br
|
91
|
+
|
92
|
+
.row
|
93
|
+
%form.form{id: 'upload-form', action: '/upload', method: 'post'}
|
94
|
+
.row
|
95
|
+
%ul.offset2
|
96
|
+
%li.radio
|
97
|
+
%input{name: 'shortener[type]', type: 'radio', value: 'video'} Video
|
98
|
+
%li.radio
|
99
|
+
%input{name: 'shortener[type]', type: 'radio', value: 'audio'} Audio
|
100
|
+
%li.radio
|
101
|
+
%input{name: 'shortener[type]', type: 'radio', value: 'image'} Image
|
102
|
+
%li.radio
|
103
|
+
%input{name: 'shortener[type]', type: 'radio', value: 'download'} Download
|
104
|
+
.row
|
105
|
+
%label.offset8.hide{id: 'shortener-display'}
|
106
|
+
.field
|
107
|
+
%label{for: 'shorterner[name]'} Name
|
108
|
+
%input{type: 'text', name: 'shortener[name]'}
|
109
|
+
.field
|
110
|
+
%label{for: 'shorterner[description]'} Description
|
111
|
+
%input{type: 'text', name: 'shortener[description]'}
|
112
|
+
.row
|
113
|
+
.actions
|
114
|
+
%input.btn.primary{type: 'submit', value: 'Shorten'}
|
115
|
+
|
116
|
+
.row
|
117
|
+
|
118
|
+
:css
|
119
|
+
.radio {
|
120
|
+
display: inline;
|
121
|
+
margin-right: 20px;
|
122
|
+
}
|
123
|
+
|
124
|
+
:javascript
|
125
|
+
$('#upload-form').submit(function(e){
|
126
|
+
e.preventDefault();
|
127
|
+
$('#swfupload-control').swfupload('startUpload');
|
128
|
+
});
|
129
|
+
|
130
|
+
|