short 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. data/Rakefile +3 -1
  2. data/lib/shortener/server/public/css/bootstrap-responsive.min.css +3 -0
  3. data/lib/shortener/server/public/css/bootstrap.min.css +610 -0
  4. data/lib/shortener/server/public/css/colorbox.css +42 -0
  5. data/lib/shortener/server/public/css/shortener.css +16 -0
  6. data/lib/shortener/server/public/images/sort_asc.png +0 -0
  7. data/lib/shortener/server/public/images/sort_both.png +0 -0
  8. data/lib/shortener/server/public/images/sort_desc.png +0 -0
  9. data/lib/shortener/server/public/js/bootstrap.min.js +1 -0
  10. data/lib/shortener/server/public/js/jquery.colorbox.js +877 -0
  11. data/lib/shortener/server/public/js/jquery.tablesorter.min.js +4 -0
  12. data/lib/shortener/server/public/{site.js → js/site.js} +25 -2
  13. data/lib/shortener/server/views/add.haml +47 -19
  14. data/lib/shortener/server/views/display.haml +7 -6
  15. data/lib/shortener/server/views/index.haml +3 -2
  16. data/lib/shortener/server/views/layout.haml +16 -7
  17. data/lib/shortener/server/views/upload.haml +93 -120
  18. data/lib/shortener/server.rb +14 -2
  19. data/lib/shortener/tasks/heroku.rb +4 -3
  20. data/lib/shortener/version.rb +1 -1
  21. metadata +25 -18
  22. data/lib/shortener/server/public/jquery-swfupload.js +0 -64
  23. data/lib/shortener/server/public/jquery.min.js +0 -18
  24. data/lib/shortener/server/public/patched.bootstrap.min.css +0 -370
  25. /data/lib/shortener/server/public/{delete-icon.png → images/delete-icon.png} +0 -0
  26. /data/lib/shortener/server/public/{jquery-swfupload-min.js → js/jquery-swfupload-min.js} +0 -0
  27. /data/lib/shortener/server/public/{jquery.jplayer.min.js → js/jquery.jplayer.min.js} +0 -0
  28. /data/lib/shortener/server/public/{swfupload.js → js/swfupload.js} +0 -0
@@ -0,0 +1,4 @@
1
+
2
+ (function($){$.extend({tablesorter:new
3
+ function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",cssChildRow:"expand-child",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,sortLocaleCompare:true,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'/\.|\,/g',onRenderHeader:null,selectorHeaders:'thead th',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}if(table.tBodies.length==0)return;var rows=table.tBodies[0].rows;if(rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,rows,-1,i);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,rows,rowIndex,cellIndex){var l=parsers.length,node=false,nodeValue=false,keepLooking=true;while(nodeValue==''&&keepLooking){rowIndex++;if(rows[rowIndex]){node=getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex);nodeValue=trimAndGetNodeText(table.config,node);if(table.config.debug){log('Checking if value was empty on row:'+rowIndex);}}else{keepLooking=false;}}for(var i=1;i<l;i++){if(parsers[i].is(nodeValue,table,node)){return parsers[i];}}return parsers[0];}function getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex){return rows[rowIndex].cells[cellIndex];}function trimAndGetNodeText(config,node){return $.trim(getElementText(config,node));}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=$(table.tBodies[0].rows[i]),cols=[];if(c.hasClass(table.config.cssChildRow)){cache.row[cache.row.length-1]=cache.row[cache.row.length-1].add(c);continue;}cache.row.push(c);for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c[0].cells[j]),table,c[0].cells[j]));}cols.push(cache.normalized.length);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){var text="";if(!node)return"";if(!config.supportsTextContent)config.supportsTextContent=node.textContent||false;if(config.textExtraction=="simple"){if(config.supportsTextContent){text=node.textContent;}else{if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){text=node.childNodes[0].innerHTML;}else{text=node.innerHTML;}}}else{if(typeof(config.textExtraction)=="function"){text=config.textExtraction(node);}else{text=$(node).text();}}return text;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){var pos=n[i][checkCell];rows.push(r[pos]);if(!table.config.appender){var l=r[pos].length;for(var j=0;j<l;j++){tableBody[0].appendChild(r[pos][j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false;var header_index=computeTableHeaderCellIndexes(table);$tableHeaders=$(table.config.selectorHeaders,table).each(function(index){this.column=header_index[this.parentNode.rowIndex+"-"+this.cellIndex];this.order=formatSortingOrder(table.config.sortInitialOrder);this.count=this.order;if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(checkHeaderOptionsSortingLocked(table,index))this.order=this.lockedOrder=checkHeaderOptionsSortingLocked(table,index);if(!this.sortDisabled){var $th=$(this).addClass(table.config.cssHeader);if(table.config.onRenderHeader)table.config.onRenderHeader.apply($th);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function computeTableHeaderCellIndexes(t){var matrix=[];var lookup={};var thead=t.getElementsByTagName('THEAD')[0];var trs=thead.getElementsByTagName('TR');for(var i=0;i<trs.length;i++){var cells=trs[i].cells;for(var j=0;j<cells.length;j++){var c=cells[j];var rowIndex=c.parentNode.rowIndex;var cellId=rowIndex+"-"+c.cellIndex;var rowSpan=c.rowSpan||1;var colSpan=c.colSpan||1
4
+ var firstAvailCol;if(typeof(matrix[rowIndex])=="undefined"){matrix[rowIndex]=[];}for(var k=0;k<matrix[rowIndex].length+1;k++){if(typeof(matrix[rowIndex][k])=="undefined"){firstAvailCol=k;break;}}lookup[cellId]=firstAvailCol;for(var k=rowIndex;k<rowIndex+rowSpan;k++){if(typeof(matrix[k])=="undefined"){matrix[k]=[];}var matrixrow=matrix[k];for(var l=firstAvailCol;l<firstAvailCol+colSpan;l++){matrixrow[l]="x";}}}}return lookup;}function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function checkHeaderOptionsSortingLocked(table,i){if((table.config.headers[i])&&(table.config.headers[i].lockedOrder))return table.config.headers[i].lockedOrder;return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){return(v.toLowerCase()=="desc")?1:0;}else{return(v==1)?1:0;}}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(table.config.parsers[c].type=="text")?((order==0)?makeSortFunction("text","asc",c):makeSortFunction("text","desc",c)):((order==0)?makeSortFunction("numeric","asc",c):makeSortFunction("numeric","desc",c));var e="e"+i;dynamicExp+="var "+e+" = "+s;dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";if(table.config.debug){benchmark("Evaling expression:"+dynamicExp,new Date());}eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function makeSortFunction(type,direction,index){var a="a["+index+"]",b="b["+index+"]";if(type=='text'&&direction=='asc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+a+" < "+b+") ? -1 : 1 )));";}else if(type=='text'&&direction=='desc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+b+" < "+a+") ? -1 : 1 )));";}else if(type=='numeric'&&direction=='asc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+a+" - "+b+"));";}else if(type=='numeric'&&direction=='desc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+b+" - "+a+"));";}};function makeSortText(i){return"((a["+i+"] < b["+i+"]) ? -1 : ((a["+i+"] > b["+i+"]) ? 1 : 0));";};function makeSortTextDesc(i){return"((b["+i+"] < a["+i+"]) ? -1 : ((b["+i+"] > a["+i+"]) ? 1 : 0));";};function makeSortNumeric(i){return"a["+i+"]-b["+i+"];";};function makeSortNumericDesc(i){return"b["+i+"]-a["+i+"];";};function sortText(a,b){if(table.config.sortLocaleCompare)return a.localeCompare(b);return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){if(table.config.sortLocaleCompare)return b.localeCompare(a);return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$.data(this,"tablesorter",config);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){$this.trigger("sortStart");var $cell=$(this);var i=this.column;this.order=this.count++%2;if(this.lockedOrder)this.order=this.lockedOrder;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){var me=this;setTimeout(function(){me.config.parsers=buildParserCache(me,$headers);cache=buildCache(me);},1);}).bind("updateCell",function(e,cell){var config=this.config;var pos=[(cell.parentNode.rowIndex-1),cell.cellIndex];cache.normalized[pos[0]][pos[1]]=config.parsers[pos[1]].format(getElementText(config,cell),cell);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){return/^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g,'')));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLocaleLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}var $tr,row=-1,odd;$("tr:visible",table.tBodies[0]).each(function(i){$tr=$(this);if(!$tr.hasClass(table.config.cssChildRow))row++;odd=(row%2==0);$tr.removeClass(table.config.widgetZebra.css[odd?0:1]).addClass(table.config.widgetZebra.css[odd?1:0])});if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);
@@ -1,7 +1,7 @@
1
1
  $(function(){
2
2
 
3
3
  /* pretty much yoinked exactly from jQuery site */
4
- $("#add-form").submit(function(event) {
4
+ $("#nav-add-form").submit(function(event) {
5
5
 
6
6
  /* stop form from submitting normally */
7
7
  event.preventDefault();
@@ -14,10 +14,12 @@ $(function(){
14
14
 
15
15
  /* Send the data using post and put the results in a div */
16
16
  $.post( this.action + '.json', formData, function( data ) {
17
- $( "#main" ).append( data.html );
17
+ $( "#display-new-shorts" ).append( data.html );
18
18
  }
19
19
  );
20
20
 
21
+ $('#nav-add-form > input[name="shortener[url]"]').val("");
22
+
21
23
  });
22
24
 
23
25
  $('.delete-button').click(function(event){
@@ -33,4 +35,25 @@ $(function(){
33
35
  }
34
36
  });
35
37
  });
38
+
39
+ $('.colorbox').each(function(index){
40
+ $(this).colorbox({href: $(this).attr('href') + '?boxify=true' });
41
+ });
42
+
43
+ $(".tablesorter:has(tbody tr)").tablesorter();
44
+
36
45
  });
46
+ window.advancedShown = false;
47
+ window.showHideAdvanced = function() {
48
+ if(window.advancedShown === false) {
49
+ $('#advanced-toggle').text('Hide Advanced Options')
50
+ $('.advanced').removeClass('hide');
51
+ $('.colorbox').colorbox.resize();
52
+ } else {
53
+ $('#advanced-toggle').text('Show Advanced Options')
54
+ $('.advanced').addClass('hide');
55
+ $('.colorbox').colorbox.resize();
56
+ }
57
+ window.advancedShown = !window.advancedShown;
58
+ }
59
+
@@ -1,22 +1,50 @@
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'}
1
+ #shortener.row(style="margin-top: 40px;margin-bottom:75px;")
2
+ %form{:id => 'add-form',:name => "shortener", :action => "/add", :method => "post", :class => boxify_class(2, nil, nil, 'form-horizontal')}
3
+ .control-group
4
+ %label.control-label{:for => "shortener[url]"} Url to Shorten:
5
+ .controls
6
+ %input{:type => "text", :name => "shortener[url]", :class => "text"}
7
+ %input{:type => "submit", :value => "Shorten", :class => "btn primary"}
8
+ %a#advanced-toggle{:onClick => 'window.showHideAdvanced();', href: '#'} Show Advanced Options
9
+ .control-group.advanced
10
+ %label{:for => 'shortener[expire]', :class => 'control-label advanced'} Time till Expired:
11
+ .controls
12
+ %input{:type => 'text', :name => 'shortener[expire]', :class => 'text advanced'}
13
+ .control-group.advanced
14
+ %label{:for => 'shortener[max-clicks]', :class => 'control-label advanced'} Max Clicks:
15
+ .controls
16
+ %input{:type => 'text', :name => 'shortener[max-clicks]', :class => 'text advanced'}
17
+ .control-group.advanced
18
+ %label{:for => 'shortener[desired-short]', :class => 'control-label advanced'} Desired Short:
19
+ .controls
20
+ %input{:type => 'text', :name => 'shortener[desired-short]', :class => 'text advanced'}
21
+ .control-group.advanced
22
+ %label{:for => 'shortener[allow-override]', :class => 'control-label'} Allow Random Override:
23
+ .controls
24
+ %input{:type => 'checkbox', :name => 'shortener[allow-override]', :class => 'text advanced', :value => 'true'}
19
25
  :javascript
20
26
  $(function(){
21
- $('.advanced').hide();
27
+ $('.advanced').addClass('hide');
28
+ $("#add-form").submit(function(event) {
29
+
30
+ /* stop form from submitting normally */
31
+ event.preventDefault();
32
+
33
+ // my best take so far at scraping form data
34
+ var formData = {};
35
+ $.each($(this).serializeArray(), function(i, field) {
36
+ formData[field.name] = field.value;
37
+ });
38
+
39
+ /* Send the data using post and put the results in a div */
40
+ $.post( this.action + '.json', formData, function( data ) {
41
+ $( "#display-add-new-shorts" ).append( data.html );
42
+ }
43
+ );
44
+
45
+ });
22
46
  })
47
+ #display-add-new-shorts{class: boxify_class(3)}
48
+
49
+ :css
50
+ .hide { display: none;}
@@ -1,6 +1,7 @@
1
- #link_display.row
2
- - classs = @data['s3'].nil? ? 'offset5' : ''
3
- %div.span4{class: classs}
4
- %h4= @url
5
- %div.span2
6
- = clippy(@url)
1
+ #link_display
2
+ .alert.alert-success{style: 'padding-bottom:25px;'}
3
+ %div.span2{class: 'offset1'}
4
+ %h4= @url
5
+ %div.span2
6
+ = clippy(@url, '#dff0d8')
7
+ %a.close{'data-dismiss' => 'alert', href: '#'}×
@@ -1,5 +1,6 @@
1
+ #display-new-shorts.container
1
2
  #shorterner-index
2
- %table
3
+ %table.table.table-striped.tablesorter
3
4
  %thead
4
5
  %tr
5
6
  %th Shortened
@@ -20,6 +21,6 @@
20
21
  %td= short['max-clicks'] || "&infin;"
21
22
  %td
22
23
  %a{href: "/delete/#{short['shortened']}", class: 'delete-button'}
23
- %img{src: 'delete-icon.png', alt: 'delete!', width: '16px', height: '16px'}
24
+ %img{src: 'images/delete-icon.png', alt: 'delete!', width: '16px', height: '16px'}
24
25
  %td= clippy("#{base_url}/#{short['shortened']}")
25
26
 
@@ -2,23 +2,32 @@
2
2
  %html
3
3
  %head
4
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'}
5
+ %script{src: '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js', type: 'text/javascript'}
6
+ %link{rel: 'stylesheet', type: 'text/css', href: '/css/bootstrap.min.css'}
7
+ %link{rel: 'stylesheet', type: 'text/css', href: '/css/bootstrap-responsive.min.css'}
8
+ %link{rel: 'stylesheet', type: 'text/css', href: '/css/shortener.css'}
9
+ %link{rel: 'stylesheet', type: 'text/css', href: '/css/colorbox.css'}
10
+ %script{src: '/js/site.js', type: 'text/javascript'}
11
+ %script{src: '/js/jquery.colorbox.js', type: 'text/javascript'}
12
+ %script{src: '/js/bootstrap.min.js', type: 'text/javascript'}
13
+ %script{src: '/js/jquery.tablesorter.min.js', type: 'text/javascript'}
8
14
  %body{:'padding-top' => '60px'}
9
15
 
10
- %div.topbar
11
- %div.topbar-inner
16
+ %div.navbar
17
+ %div.navbar-inner
12
18
  %div.container
13
19
  %a{class: 'brand', href: "/"} Shortener
14
20
  %ul.nav
21
+ %li
22
+ %form{:id => 'nav-add-form',:name => "shortener", :action => "/add", :method => "post", :class => 'navbar-search pull-left'}
23
+ %input{:type => "text", :name => "shortener[url]", :class => "search-query span2", placeholder: 'Shorten'}
15
24
  %li
16
25
  %a{href: '/index'} Index
17
26
  %li
18
- %a{href: '/add'} Add
27
+ %a.colorbox{href: '/add'} Advanced Add
19
28
  - if $conf.s3_available
20
29
  %li
21
- %a{href: '/upload'} Upload
30
+ %a.colorbox{href: '/upload'} Upload
22
31
 
23
32
  #main.container(style="margin-top: 40px;")
24
33
  = yield
@@ -1,130 +1,103 @@
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.json', values, function(data){
66
- $('#shortener-display').html(data.html)
67
- .removeClass('hide');
68
- });
1
+ %script{src: "js/swfupload.js"}
2
+ %script{src: "js/jquery-swfupload-min.js"}
3
+ .row
4
+ %form.form-horizontal.span6{id: 'upload-form', action: '/upload', method: 'post'}
5
+ .control-group
6
+ %label.control-label Select File:
7
+ .controls
8
+ %div{:id=> "swfupload-control"}
9
+ %ol{:id=> "log"}
10
+ %span{:id=> "span-button-placeholder"}
11
+ %span{id: 'file-name-placeholder'}
12
+ .control-group.hideable
13
+ %label.control-label Display Type:
14
+ .controls
15
+ %label.radio.inline
16
+ %input{name: 'shortener[type]', type: 'radio', value: 'video'}
17
+ Video
18
+ %label.radio.inline
19
+ %input{name: 'shortener[type]', type: 'radio', value: 'audio'}
20
+ Audio
21
+ %label.radio.inline
22
+ %input{name: 'shortener[type]', type: 'radio', value: 'image'}
23
+ Image
24
+ %label.radio.inline
25
+ %input{name: 'shortener[type]', type: 'radio', value: 'download'}
26
+ Download
27
+ .control-group.hideable
28
+ %label.control-label{for: 'shorterner[name]'} Name
29
+ .controls
30
+ %input{type: 'text', name: 'shortener[name]'}
31
+ .control-group.hideable
32
+ %label.control-label{for: 'shorterner[description]'} Description
33
+ .controls
34
+ %input{type: 'text', name: 'shortener[description]'}
35
+ .form-actions.hideable
36
+ %input.btn-primary{type: 'submit', value: 'Shorten'}
37
+ .row
38
+ #progressbar.span4.offset1{style: 'display:none;'}
39
+ .progress.progress-danger.active.progress-striped
40
+ .bar{style: "width: 0%"}
69
41
 
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
- });
42
+ #display-up-new-shorts{class: boxify_class(nil, nil, 'container')}
76
43
 
77
- });
78
- </script>
44
+ :javascript
45
+ $(function(){
46
+ $('#swfupload-control').swfupload({
47
+ // Backend Settings
48
+ upload_url: "#{@upload_url}",
49
+ http_success : [ 200, 201, 204 ], // FOR AWS
79
50
 
80
- .row
81
- #progressbar.span8{style: 'display:none;'}
82
- .progress.danger.active.striped
83
- .bar{style: "width: 0%"}
51
+ // File Upload Settings
52
+ file_size_limit : "102400", // 100MB
53
+ file_types : "*.*",
54
+ file_types_description : "All Files",
55
+ file_upload_limit : "10",
56
+ file_queue_limit : "0",
57
+ file_post_name : "file", // FOR AWS
84
58
 
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
59
+ // Button settings
60
+ button_image_url : "/images/XPButtonUploadText_61x22.png",
61
+ button_placeholder_id : "span-button-placeholder",
62
+ button_width: 61,
63
+ button_height: 22,
91
64
 
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
- #shortener-display.offset8.hide
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'}
65
+ // Flash Settings
66
+ flash_url : "/flash/swfupload.swf",
67
+ //debug: true,
68
+ post_params: #{@post.to_json} // FOR AWS
115
69
 
116
- .row
70
+ })
71
+ .bind('fileQueued', function(event, file){
72
+ $(this).swfupload('setButtonDisabled', true);
73
+ $('#file-name-placeholder').text(file.name);
74
+ })
75
+ .bind('uploadStart', function(event, file){
76
+ $('#progressbar').show();
77
+ $('.hideable').hide();
78
+ $('.form-actions').hide();
79
+ })
80
+ .bind('uploadProgress', function(event, file, bytesLoaded){
81
+ var avg = bytesLoaded / file.size * 100;
82
+ $('#progressbar .bar').css('width', avg + '%' );
83
+ })
84
+ .bind('uploadSuccess', function(event, file, serverData){
85
+ var values = $('#upload-form').serialize();
86
+ values += '&shortener%5bfile_name%5d=' + file.name;
87
+ $.post('/upload.json', values, function(data){
88
+ $('#display-up-new-shorts').append(data.html)
89
+ });
117
90
 
118
- :css
119
- .radio {
120
- display: inline;
121
- margin-right: 20px;
122
- }
91
+ })
92
+ .bind('uploadComplete', function(event, file){
93
+ $('#progressbar .bar').css('width', '100%')
94
+ $('#progressbar .active').removeClass('active');
95
+ $('.control-group').hide();
96
+ })
123
97
 
124
- :javascript
125
- $('#upload-form').submit(function(e){
126
- e.preventDefault();
127
- $('#swfupload-control').swfupload('startUpload');
98
+ $('#upload-form').submit(function(e){
99
+ e.preventDefault();
100
+ $('#swfupload-control').swfupload('startUpload');
101
+ });
128
102
  });
129
103
 
130
-
@@ -205,6 +205,16 @@ class Shortener
205
205
  hsh.keys.map {|k| [k, hsh[k]] }.flatten
206
206
  end
207
207
 
208
+ def boxify_class(int, boxify_classes = '', nonbox_classes = '', other_classes = '')
209
+ str = if @boxify
210
+ "#{other_classes} #{boxify_classes}"
211
+ else
212
+ "#{other_classes} #{nonbox_classes}"
213
+ end
214
+ str = str + " offset#{int}" unless !int.nil? && @boxify
215
+ str
216
+ end
217
+
208
218
  end
209
219
 
210
220
  before do
@@ -216,7 +226,8 @@ class Shortener
216
226
  end
217
227
 
218
228
  get '/add' do
219
- haml :add
229
+ @boxify = !params['boxify'].nil?
230
+ haml :add, layout: !@boxify
220
231
  end
221
232
 
222
233
  get '/index.?:format?' do
@@ -259,7 +270,8 @@ class Shortener
259
270
  }
260
271
 
261
272
  @upload_url = "http://#{$conf.s3_bucket}.s3.amazonaws.com/"
262
- haml :upload
273
+ @boxify = !params['boxify'].nil?
274
+ haml :upload, layout: !@boxify
263
275
  end
264
276
 
265
277
  #get '/:id.?:format?' do
@@ -64,8 +64,8 @@ namespace :short do
64
64
  desc "Build a Heroku Ready Git repo"
65
65
  task :build do
66
66
  FileUtils.mkdir(File.join(Dir.pwd, 'shortener-heroku')) unless $existing_repo
67
- [:'server', :'server/public', :'server/views',
68
- :'server/views/s3', :'server/public/flash',
67
+ [:'server', :'server/public', :'server/views', :'server/views/s3',
68
+ :'server/public/flash', :'server/public/js', :'server/public/css',
69
69
  :'server/public/skin', :'server/public/images',
70
70
  :'server/public/skin/blue.monday'].each do |f|
71
71
  unless File.exist?(_file(f))
@@ -76,7 +76,8 @@ namespace :short do
76
76
 
77
77
  ['server', 'server/public', 'server/views', :'server/views/s3',
78
78
  :'server/public/flash', :'server/public/images', :'server/public/skin',
79
- :'server/public/skin/blue.monday'].each do |end_point|
79
+ :'server/public/skin/blue.monday', :'server/public/js',
80
+ :'server/public/css'].each do |end_point|
80
81
  Dir["#{$gem_dir}/#{end_point}/**"].each do |f|
81
82
  next if File.directory?(f)
82
83
  end_point = _file(:"#{_ep(f)}")
@@ -1,6 +1,6 @@
1
1
 
2
2
  class Shortener
3
3
 
4
- VERSION = '0.5.2'
4
+ VERSION = '0.5.3'
5
5
 
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: short
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-23 00:00:00.000000000 Z
12
+ date: 2012-03-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sinatra
16
- requirement: &70206107096800 !ruby/object:Gem::Requirement
16
+ requirement: &70315090913060 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70206107096800
24
+ version_requirements: *70315090913060
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: redis-namespace
27
- requirement: &70206107095920 !ruby/object:Gem::Requirement
27
+ requirement: &70315090911220 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70206107095920
35
+ version_requirements: *70315090911220
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: haml
38
- requirement: &70206107095340 !ruby/object:Gem::Requirement
38
+ requirement: &70315090909160 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70206107095340
46
+ version_requirements: *70315090909160
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: turn
49
- requirement: &70206107094660 !ruby/object:Gem::Requirement
49
+ requirement: &70315090904700 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70206107094660
57
+ version_requirements: *70315090904700
58
58
  description: A (hopefully) easy and handy deployable APIable way to shorten links.
59
59
  email:
60
60
  - jake@jakewilkins.com
@@ -75,22 +75,29 @@ files:
75
75
  - lib/shortener/server/Gemfile
76
76
  - lib/shortener/server/Gemfile.lock
77
77
  - lib/shortener/server/config.ru.template
78
- - lib/shortener/server/public/delete-icon.png
78
+ - lib/shortener/server/public/css/bootstrap-responsive.min.css
79
+ - lib/shortener/server/public/css/bootstrap.min.css
80
+ - lib/shortener/server/public/css/colorbox.css
81
+ - lib/shortener/server/public/css/shortener.css
79
82
  - lib/shortener/server/public/flash/Jplayer.swf
80
83
  - lib/shortener/server/public/flash/clippy.swf
81
84
  - lib/shortener/server/public/flash/swfupload.swf
82
85
  - lib/shortener/server/public/images/XPButtonUploadText_61x22.png
83
- - lib/shortener/server/public/jquery-swfupload-min.js
84
- - lib/shortener/server/public/jquery-swfupload.js
85
- - lib/shortener/server/public/jquery.jplayer.min.js
86
- - lib/shortener/server/public/jquery.min.js
87
- - lib/shortener/server/public/patched.bootstrap.min.css
88
- - lib/shortener/server/public/site.js
86
+ - lib/shortener/server/public/images/delete-icon.png
87
+ - lib/shortener/server/public/images/sort_asc.png
88
+ - lib/shortener/server/public/images/sort_both.png
89
+ - lib/shortener/server/public/images/sort_desc.png
90
+ - lib/shortener/server/public/js/bootstrap.min.js
91
+ - lib/shortener/server/public/js/jquery-swfupload-min.js
92
+ - lib/shortener/server/public/js/jquery.colorbox.js
93
+ - lib/shortener/server/public/js/jquery.jplayer.min.js
94
+ - lib/shortener/server/public/js/jquery.tablesorter.min.js
95
+ - lib/shortener/server/public/js/site.js
96
+ - lib/shortener/server/public/js/swfupload.js
89
97
  - lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.css
90
98
  - lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.jpg
91
99
  - lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.seeking.gif
92
100
  - lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.video.play.png
93
- - lib/shortener/server/public/swfupload.js
94
101
  - lib/shortener/server/views/add.haml
95
102
  - lib/shortener/server/views/display.haml
96
103
  - lib/shortener/server/views/index.haml