short 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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