Adding support for multiple editors for Pro users.

master
Nick Sergeant 2013-02-04 14:40:45 -05:00
parent 8bea4dc3c8
commit 6e29fee3bd
12 changed files with 186 additions and 23 deletions

View File

@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'UserProfile.default_editor'
db.add_column('accounts_userprofile', 'default_editor',
self.gf('django.db.models.fields.CharField')(default='C', max_length=250),
keep_default=False)
def backwards(self, orm):
# Deleting field 'UserProfile.default_editor'
db.delete_column('accounts_userprofile', 'default_editor')
models = {
'accounts.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'blog_domain': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'blog_theme': ('django.db.models.fields.CharField', [], {'default': "'D'", 'max_length': '1'}),
'blog_title': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'default_editor': ('django.db.models.fields.CharField', [], {'default': "'C'", 'max_length': '250'}),
'disqus_shortname': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'gittip_username': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_pro': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'stripe_id': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
},
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['accounts']

View File

@ -3,6 +3,11 @@ from django.db import models
class UserProfile(models.Model):
EDITOR_CHOICES = (
('C', 'CodeMirror'),
('T', 'Textarea'),
)
THEME_CHOICES = (
('D', 'Default'),
('A', 'Pro Adams'),
@ -15,6 +20,7 @@ class UserProfile(models.Model):
blog_title = models.CharField(max_length=250, null=True, blank=True)
blog_theme = models.CharField(max_length=1, null=False, blank=False, default='D', choices=THEME_CHOICES)
blog_domain = models.CharField(max_length=250, null=True, blank=True)
default_editor = models.CharField(max_length=250, null=False, blank=False, default='C', choices=EDITOR_CHOICES)
gittip_username = models.CharField(max_length=250, null=True, blank=True)
disqus_shortname = models.CharField(max_length=250, null=True, blank=True)

View File

@ -44,6 +44,12 @@
<span class="help-block">Like 'snipt.nicksergeant.com' or 'nicksergeant.com' (without quotes). Set your CNAME / A-record to point to 96.126.110.160</span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="id_default_editor">Default editor:</label>
<div class="controls">
{{ form.default_editor }}
</div>
</div>
<div class="control-group">
<label class="control-label" for="id_gittip_username">Gittip username:</label>
<div class="controls">

View File

@ -25,6 +25,8 @@ def account(request):
'blog_theme': profile.blog_theme,
'blog_domain': profile.blog_domain,
'default_editor': profile.default_editor,
'gittip_username': profile.gittip_username,
'disqus_shortname': profile.disqus_shortname,
})

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2125,6 +2125,11 @@ body.editing {
.CodeMirror-matchingbracket {
color: #32A8F6;
}
textarea.editor {
border: 0;
margin: 0;
width: 684px;
}
}
header {
h1 {
@ -2147,20 +2152,20 @@ body.editing {
margin-top: 0;
width: 243px;
label {
margin: 20px 0;
& > span {
color: #32A8F6;
display: block;
font: bold 12px $Helvetica;
margin-bottom: 5px;
text-transform: uppercase;
}
}
div.in {
padding-left: 10px;
label {
margin: 20px 0;
& > span {
color: #32A8F6;
display: block;
font: bold 12px $Helvetica;
margin-bottom: 5px;
text-transform: uppercase;
}
}
& > label {
margin-top: 6px;
}
@ -2208,6 +2213,13 @@ body.editing {
}
}
}
div.editor-settings {
padding-left: 10px;
label {
margin: 0;
}
}
}
}
}

View File

@ -144,7 +144,9 @@ window.ui_halted=false;},events:{'showKeyboardShortcuts':'showKeyboardShortcuts'
(function(Snipt){Snipt.SniptModel=Backbone.Model.extend({toSafe:function(){var snipt=this.toJSON();snipt.code=this.escape('code');snipt.title=this.escape('title');snipt.tags_list=this.escape('tags_list');if(typeof snipt.tags==='object'){for(var i;i<snipt.tags.length;i++){snipt.tags[i].name=_.escape(snipt.tags[i].name);}}
return snipt;}});Snipt.SniptView=Backbone.View.extend({tagName:'article',initialize:function(){this.model.view=this;this.model.bind('change',this.render,this);this.template=_.template($('#snipt').html());this.editTemplate=_.template($('#edit').html());this.initLocalVars();this.initLineNumbers();},events:{'click a.copy':'copyFromClick','click a.edit':'edit','click a.favorite':'favoriteToggle','click a.embed':'embedFromClick','click a.expand':'expand','click .container':'selectFromClick','copyClose':'copyClose','copyRaw':'copy','detail':'detail','deselect':'deselect','destroy':'destroy','edit':'edit','embed':'embed','embedClose':'embedClose','expand':'expand','fadeAndRemove':'fadeAndRemove','goToAuthor':'goToAuthor','next':'next','prev':'prev','selectSnipt':'select'},copy:function(){$('textarea',this.$copyModal).remove();window.ui_halted=true;this.$copyModalBody.append('<textarea class="raw"></textarea>');$textarea=$('textarea.raw',this.$copyModalBody).val(this.model.get('code'));this.$copyModal.modal('show');$textarea.select();},copyClose:function(){$('textarea',this.$copyModal).remove();},copyFromClick:function(){this.copy();return false;},deselect:function(){this.$el.removeClass('selected');window.$selected=false;},detail:function(){window.location=this.model.get('absolute_url');},destroy:function(){this.model.destroy();},edit:function(){window.editing=true;window.ui_halted=true;this.select();that=this;var editPane=this.editTemplate({snipt:this.model.toSafe()});window.site.$main.hide();window.site.$body.addClass('detail editing');window.site.$main_edit.html(editPane);$('option[value="'+this.model.get('lexer')+'"]',window.site.$main_edit).attr('selected','selected');var $selectLexer=$('select#id_lexer',window.site.$main_edit);$selectLexer.chosen();$('label.blog-post input',window.site.$main_edit).on('change',function(){var $checkbox=$(this);var $label=$checkbox.parent();var $publish_date=$label.siblings('label.publish-date');if($checkbox.attr('checked')){$label.removeClass('is-not-blog-post').addClass('is-blog-post');$publish_date.show();}else{$label.addClass('is-not-blog-post').removeClass('is-blog-post');$publish_date.hide();}
return false;}).trigger('change');$('label.public input',window.site.$main_edit).on('change',function(){var $checkbox=$(this);var $label=$checkbox.parent();if($checkbox.attr('checked')){$label.removeClass('is-private').addClass('is-public');}else{$label.addClass('is-private').removeClass('is-public');}
return false;}).trigger('change');window.site.$main_edit.show();var $editor=$('div#editor',window.site.$main_edit);window.editor=CodeMirror($editor.get(0),{autofocus:true,fixedGutter:true,gutter:true,indentUnit:4,lineNumbers:true,javascriptHint:true,matchBrackets:true,mode:that.guessCodeMirrorLexer($selectLexer.val()),value:that.model.get('code')});$selectLexer.change(function(){var $selectedLexer=$('option:selected',$selectLexer);window.editor.setOption('mode',that.guessCodeMirrorLexer($selectedLexer.val()));});window.editor.setSize('100%',$(window).height()-147);$('textarea, input',window.site.$main_edit).bind('keydown','esc',function(e){$(this).blur();return false;});$('button.delete',window.site.$main_edit).on('click',function(){if(confirm('Are you sure you want to delete this snipt?')){that.model.destroy();window.site.snipt_list.escapeUI(true);}
return false;}).trigger('change');window.site.$main_edit.show();this.$editorCodeMirror=$('div.editor',window.site.$main_edit);this.$editorTextarea=$('textarea.editor',window.site.$main_edit);window.editor=CodeMirror(this.$editorCodeMirror.get(0),{autofocus:true,fixedGutter:true,gutter:true,indentUnit:4,lineNumbers:true,javascriptHint:true,matchBrackets:true,mode:that.guessCodeMirrorLexer($selectLexer.val()),value:that.model.get('code')});$selectLexer.change(function(){var $selectedLexer=$('option:selected',$selectLexer);window.editor.setOption('mode',that.guessCodeMirrorLexer($selectedLexer.val()));});var editorHeight=$(window).height()-147;window.editor.setSize('100%',editorHeight);this.$editorTextarea.height(editorHeight-8);$('textarea, input',window.site.$main_edit).bind('keydown','esc',function(e){$(this).blur();return false;});if(window.user_is_pro){var $selectEditor=$('select#id_editor',window.site.$main_edit);$selectEditor.chosen();$selectEditor.change(function(){var newEditor=$selectEditor.val();if(newEditor==='textarea'){that.$editorCodeMirror.hide();that.$editorTextarea.show();that.$editorTextarea.val(window.editor.getValue());}
if(newEditor==='codemirror'){that.$editorTextarea.hide();that.$editorCodeMirror.show();window.editor.setValue(that.$editorTextarea.val());}});if(window.default_editor!='codemirror'){$selectEditor.val(window.default_editor);$selectEditor.trigger('liszt:updated');$selectEditor.trigger('change');}}
$('button.delete',window.site.$main_edit).on('click',function(){if(confirm('Are you sure you want to delete this snipt?')){that.model.destroy();window.site.snipt_list.escapeUI(true);}
return false;});$('button.cancel',window.site.$main_edit).on('click',function(){window.site.snipt_list.escapeUI();return false;});$('button.save',window.site.$main_edit).on('click',function(){$('button.cancel').text('Close');that.save();return false;});$('button.save-and-close',window.site.$main_edit).on('click',function(){that.save();window.site.snipt_list.escapeUI();return false;});window.scrollTo(0,0);return false;},embed:function(){$('textarea',this.$embedModal).remove();window.ui_halted=true;this.$embedModalBody.append('<textarea class="raw"></textarea>');$textarea=$('textarea.raw',this.$embedModalBody).val('<script type="text/javascript" src="'+this.model.get('embed_url')+'"></script>');this.$embedModal.modal('show');$textarea.select();},embedFromClick:function(){this.embed();return false;},embedClose:function(){$('textarea',this.$embedModal).remove();},expand:function(){this.$container.toggleClass('expanded',100);this.$tags.toggleClass('expanded');this.select();return false;},fadeAndRemove:function(){var $toRemove=$(this.el);var $nextSnipt=$toRemove.next('article.snipt');window.$selected=false;$toRemove.fadeOut('fast',function(){$(this).remove();$nextSnipt.trigger('selectSnipt');});return false;},goToAuthor:function(){window.location=this.model.get('user').absolute_url;},guessCodeMirrorLexer:function(val){if(val==='html'){return'htmlmixed';}
if(val==='js')return'javascript';if(val==='rb')return'ruby';return val;},favoriteToggle:function(){var that=this;if(this.$el.hasClass('favorited')){$.ajax('/api/private/favorite/'+this.model.get('favorite_id')+'/',{type:'delete',success:function(){that.$el.removeClass('favorited');that.$favorite.text('Favorite');},headers:{'Authorization':'ApiKey '+window.user+':'+window.api_key}});}else{$.ajax('/api/private/favorite/',{data:'{"snipt": '+this.model.get('id')+'}',contentType:'application/json',type:'post',success:function(resp){that.$el.addClass('favorited');that.model.set({'favorite_id':resp.id},{'silent':true});that.$favorite.text('Favorited');},headers:{'Authorization':'ApiKey '+window.user+':'+window.api_key}});}
return false;},initLineNumbers:function(){var lines=$('span.special',this.$el);var that=this;$.each(lines,function(){var l=$(this);var num=l.text().trim();var url=that.model.get('absolute_url');l.replaceWith('<a href="'+url+'#line-'+num+'">'+num+'</a>');});},initLocalVars:function(){this.$aside=$('aside',this.$el);this.$container=$('div.container',this.$el);this.$copyModal=$('div.copy-modal',this.$el);this.$copyModalBody=$('div.modal-body',this.$copyModal);this.$embedModal=$('div.embed-modal',this.$el);this.$embedModalBody=$('div.modal-body',this.$embedModal);this.$favorite=$('a.favorite',this.$el);this.$h1=$('header h1 a',this.$el);this.$tags=$('section.tags ul',this.$aside);this.$copyModal.on('hidden',function(e){$(this).parent().trigger('copyClose');window.ui_halted=false;window.from_modal=true;});this.$embedModal.on('hidden',function(e){$(this).parent().trigger('embedClose');window.ui_halted=false;window.from_modal=true;});},next:function(){if(!window.ui_halted){nextSnipt=this.$el.next('article.snipt');if(nextSnipt.length){return nextSnipt.trigger('selectSnipt');}}},prev:function(){if(!window.ui_halted){prevSnipt=this.$el.prev('article.snipt');if(prevSnipt.length){return prevSnipt.trigger('selectSnipt');}}},remove:function(){return false;},render:function(){this.$el.html(this.template({snipt:this.model.toSafe()}));this.initLocalVars();this.initLineNumbers();if(this.model.get('blog_post')===true){this.$el.addClass('blog-post');}else{this.$el.removeClass('blog-post');}
@ -152,7 +154,8 @@ if(this.model.get('public')===true){this.$el.removeClass('private-snipt');}else{
if(this.model.get('user').username===window.user){this.$el.addClass('editable');}else{this.$el.removeClass('editable');}
if(this.model.get('line_count')>8&&!window.detail){this.$el.addClass('expandable');}else{this.$el.removeClass('expandable');}
$('script#disqus').remove();window.site.$body.append('<script id="disqus" type="text/javascript">'+$('script#disqus-template').text()+'</script>');if(this.$el.attr('id')==='new-snipt'){this.$el.fadeIn('fast');this.$el.attr('id','snipt-'+this.model.get('id'));}
return this;},save:function(){$('button.save, button.save-and-close, button.delete, button.cancel',window.site.$main_edit).attr('disabled','disabled');that.model.save({'title':$('input#snipt_title').val(),'tags':$('label.tags textarea').val(),'tags_list':$('label.tags textarea').val(),'lexer':$('select[name="lexer"]').val(),'lexer_name':$('select[name="lexer"] option:selected').text(),'code':window.editor.getValue(),'blog_post':$('label.blog-post input').is(':checked'),'publish_date':$('label.publish-date input').val(),'public':$('label.public input').is(':checked')},{success:function(model,response){$('button.save, button.save-and-close, button.delete, button.cancel',window.site.$main_edit).removeAttr('disabled');},error:function(model,response){alert('There was a problem saving your snipt. We\'ve been notified. Sorry about that!');}});},select:function(fromClick){$('article.selected',window.site.snipt_list.$el).removeClass('selected');this.$el.addClass('selected');if(fromClick!==true){if(window.site.$snipts.index(this.$el)===0){window.scrollTo(0,0);}else{window.site.$html_body.animate({scrollTop:this.$el.offset().top-50},0);}}
return this;},save:function(){$('button.save, button.save-and-close, button.delete, button.cancel',window.site.$main_edit).attr('disabled','disabled');var code;if(this.$editorTextarea.is(':visible')){code=this.$editorTextarea.val();}else{code=window.editor.getValue();}
that.model.save({'title':$('input#snipt_title').val(),'tags':$('label.tags textarea').val(),'tags_list':$('label.tags textarea').val(),'lexer':$('select[name="lexer"]').val(),'lexer_name':$('select[name="lexer"] option:selected').text(),'code':code,'blog_post':$('label.blog-post input').is(':checked'),'publish_date':$('label.publish-date input').val(),'public':$('label.public input').is(':checked')},{success:function(model,response){$('button.save, button.save-and-close, button.delete, button.cancel',window.site.$main_edit).removeAttr('disabled');},error:function(model,response){alert('There was a problem saving your snipt. We\'ve been notified. Sorry about that!');}});},select:function(fromClick){$('article.selected',window.site.snipt_list.$el).removeClass('selected');this.$el.addClass('selected');if(fromClick!==true){if(window.site.$snipts.index(this.$el)===0){window.scrollTo(0,0);}else{window.site.$html_body.animate({scrollTop:this.$el.offset().top-50},0);}}
window.$selected=this.$el;},selectFromClick:function(e){this.select(true);e.stopPropagation();window.site.$aside_nav.removeClass('open');}});Snipt.SniptListView=Backbone.View.extend({el:'section#snipts',initialize:function(opts){var that=this;opts.snipts.each(this.addExistingSnipt);this.keyboardShortcuts();var cmd;if(navigator.platform=='MacPPC'||navigator.platform=='MacIntel'){cmd='Cmd';}
else{cmd='Ctrl';}
$('span.cmd-ctrl').text(cmd);$('button#add-snipt').click(function(){that.addNewSnipt();});},addExistingSnipt:function(){var $el=$(this);var $created=$('li.created',$el);var $h1=$('header h1 a',$el);var $public=$('div.public',$el);var $blog_post=$('div.blog-post',$el);var $publish_date=$('div.publish-date',$el);var $user=$('li.author a',$el);var is_public=$public.text()==='True'?true:false;var is_blog_post=$blog_post.text()==='True'?true:false;var tag_lis=$('section.tags li',$el);var tags=[];for(var i=0;i<tag_lis.length;i++){var $tag=$('a',tag_lis.eq(i));tags[i]={name:$tag.text(),absolute_url:$tag.attr('href')};}

View File

@ -89,7 +89,9 @@
this.select();
that = this;
var editPane = this.editTemplate({snipt: this.model.toSafe()});
var editPane = this.editTemplate({
snipt: this.model.toSafe()
});
// Init main view
window.site.$main.hide();
@ -135,9 +137,12 @@
window.site.$main_edit.show();
// CodeMirror editor
var $editor = $('div#editor', window.site.$main_edit);
this.$editorCodeMirror = $('div.editor', window.site.$main_edit);
window.editor = CodeMirror($editor.get(0), {
// Textarea editor
this.$editorTextarea = $('textarea.editor', window.site.$main_edit);
window.editor = CodeMirror(this.$editorCodeMirror.get(0), {
autofocus: true,
fixedGutter: true,
gutter: true,
@ -153,13 +158,47 @@
window.editor.setOption('mode', that.guessCodeMirrorLexer($selectedLexer.val()));
});
window.editor.setSize('100%', $(window).height() - 147);
// Set the heights.
var editorHeight = $(window).height() - 147;
window.editor.setSize('100%', editorHeight);
this.$editorTextarea.height(editorHeight - 8);
$('textarea, input', window.site.$main_edit).bind('keydown', 'esc', function(e) {
$(this).blur();
return false;
});
// Editor settings
if (window.user_is_pro) {
var $selectEditor = $('select#id_editor', window.site.$main_edit);
$selectEditor.chosen();
$selectEditor.change(function() {
var newEditor = $selectEditor.val();
if (newEditor === 'textarea') {
that.$editorCodeMirror.hide();
that.$editorTextarea.show();
// TODO: if we introduce other editors, we'll want to make this smarter, obviously.
that.$editorTextarea.val(window.editor.getValue());
}
if (newEditor === 'codemirror') {
that.$editorTextarea.hide();
that.$editorCodeMirror.show();
// TODO: Ditto above.
window.editor.setValue(that.$editorTextarea.val());
}
});
if (window.default_editor != 'codemirror') {
$selectEditor.val(window.default_editor);
$selectEditor.trigger('liszt:updated');
$selectEditor.trigger('change');
}
}
// Edit buttons
$('button.delete', window.site.$main_edit).on('click', function() {
if (confirm('Are you sure you want to delete this snipt?')) {
@ -365,13 +404,20 @@
$('button.save, button.save-and-close, button.delete, button.cancel',
window.site.$main_edit).attr('disabled', 'disabled');
var code;
if (this.$editorTextarea.is(':visible')) {
code = this.$editorTextarea.val();
} else {
code = window.editor.getValue();
}
that.model.save({
'title': $('input#snipt_title').val(),
'tags': $('label.tags textarea').val(),
'tags_list': $('label.tags textarea').val(),
'lexer': $('select[name="lexer"]').val(),
'lexer_name': $('select[name="lexer"] option:selected').text(),
'code': window.editor.getValue(),
'code': code,
'blog_post': $('label.blog-post input').is(':checked'),
'publish_date': $('label.publish-date input').val(),
'public': $('label.public input').is(':checked')

View File

@ -2,7 +2,9 @@
(function(Snipt){Snipt.SniptModel=Backbone.Model.extend({toSafe:function(){var snipt=this.toJSON();snipt.code=this.escape('code');snipt.title=this.escape('title');snipt.tags_list=this.escape('tags_list');if(typeof snipt.tags==='object'){for(var i;i<snipt.tags.length;i++){snipt.tags[i].name=_.escape(snipt.tags[i].name);}}
return snipt;}});Snipt.SniptView=Backbone.View.extend({tagName:'article',initialize:function(){this.model.view=this;this.model.bind('change',this.render,this);this.template=_.template($('#snipt').html());this.editTemplate=_.template($('#edit').html());this.initLocalVars();this.initLineNumbers();},events:{'click a.copy':'copyFromClick','click a.edit':'edit','click a.favorite':'favoriteToggle','click a.embed':'embedFromClick','click a.expand':'expand','click .container':'selectFromClick','copyClose':'copyClose','copyRaw':'copy','detail':'detail','deselect':'deselect','destroy':'destroy','edit':'edit','embed':'embed','embedClose':'embedClose','expand':'expand','fadeAndRemove':'fadeAndRemove','goToAuthor':'goToAuthor','next':'next','prev':'prev','selectSnipt':'select'},copy:function(){$('textarea',this.$copyModal).remove();window.ui_halted=true;this.$copyModalBody.append('<textarea class="raw"></textarea>');$textarea=$('textarea.raw',this.$copyModalBody).val(this.model.get('code'));this.$copyModal.modal('show');$textarea.select();},copyClose:function(){$('textarea',this.$copyModal).remove();},copyFromClick:function(){this.copy();return false;},deselect:function(){this.$el.removeClass('selected');window.$selected=false;},detail:function(){window.location=this.model.get('absolute_url');},destroy:function(){this.model.destroy();},edit:function(){window.editing=true;window.ui_halted=true;this.select();that=this;var editPane=this.editTemplate({snipt:this.model.toSafe()});window.site.$main.hide();window.site.$body.addClass('detail editing');window.site.$main_edit.html(editPane);$('option[value="'+this.model.get('lexer')+'"]',window.site.$main_edit).attr('selected','selected');var $selectLexer=$('select#id_lexer',window.site.$main_edit);$selectLexer.chosen();$('label.blog-post input',window.site.$main_edit).on('change',function(){var $checkbox=$(this);var $label=$checkbox.parent();var $publish_date=$label.siblings('label.publish-date');if($checkbox.attr('checked')){$label.removeClass('is-not-blog-post').addClass('is-blog-post');$publish_date.show();}else{$label.addClass('is-not-blog-post').removeClass('is-blog-post');$publish_date.hide();}
return false;}).trigger('change');$('label.public input',window.site.$main_edit).on('change',function(){var $checkbox=$(this);var $label=$checkbox.parent();if($checkbox.attr('checked')){$label.removeClass('is-private').addClass('is-public');}else{$label.addClass('is-private').removeClass('is-public');}
return false;}).trigger('change');window.site.$main_edit.show();var $editor=$('div#editor',window.site.$main_edit);window.editor=CodeMirror($editor.get(0),{autofocus:true,fixedGutter:true,gutter:true,indentUnit:4,lineNumbers:true,javascriptHint:true,matchBrackets:true,mode:that.guessCodeMirrorLexer($selectLexer.val()),value:that.model.get('code')});$selectLexer.change(function(){var $selectedLexer=$('option:selected',$selectLexer);window.editor.setOption('mode',that.guessCodeMirrorLexer($selectedLexer.val()));});window.editor.setSize('100%',$(window).height()-147);$('textarea, input',window.site.$main_edit).bind('keydown','esc',function(e){$(this).blur();return false;});$('button.delete',window.site.$main_edit).on('click',function(){if(confirm('Are you sure you want to delete this snipt?')){that.model.destroy();window.site.snipt_list.escapeUI(true);}
return false;}).trigger('change');window.site.$main_edit.show();this.$editorCodeMirror=$('div.editor',window.site.$main_edit);this.$editorTextarea=$('textarea.editor',window.site.$main_edit);window.editor=CodeMirror(this.$editorCodeMirror.get(0),{autofocus:true,fixedGutter:true,gutter:true,indentUnit:4,lineNumbers:true,javascriptHint:true,matchBrackets:true,mode:that.guessCodeMirrorLexer($selectLexer.val()),value:that.model.get('code')});$selectLexer.change(function(){var $selectedLexer=$('option:selected',$selectLexer);window.editor.setOption('mode',that.guessCodeMirrorLexer($selectedLexer.val()));});var editorHeight=$(window).height()-147;window.editor.setSize('100%',editorHeight);this.$editorTextarea.height(editorHeight-8);$('textarea, input',window.site.$main_edit).bind('keydown','esc',function(e){$(this).blur();return false;});if(window.user_is_pro){var $selectEditor=$('select#id_editor',window.site.$main_edit);$selectEditor.chosen();$selectEditor.change(function(){var newEditor=$selectEditor.val();if(newEditor==='textarea'){that.$editorCodeMirror.hide();that.$editorTextarea.show();that.$editorTextarea.val(window.editor.getValue());}
if(newEditor==='codemirror'){that.$editorTextarea.hide();that.$editorCodeMirror.show();window.editor.setValue(that.$editorTextarea.val());}});if(window.default_editor!='codemirror'){$selectEditor.val(window.default_editor);$selectEditor.trigger('liszt:updated');$selectEditor.trigger('change');}}
$('button.delete',window.site.$main_edit).on('click',function(){if(confirm('Are you sure you want to delete this snipt?')){that.model.destroy();window.site.snipt_list.escapeUI(true);}
return false;});$('button.cancel',window.site.$main_edit).on('click',function(){window.site.snipt_list.escapeUI();return false;});$('button.save',window.site.$main_edit).on('click',function(){$('button.cancel').text('Close');that.save();return false;});$('button.save-and-close',window.site.$main_edit).on('click',function(){that.save();window.site.snipt_list.escapeUI();return false;});window.scrollTo(0,0);return false;},embed:function(){$('textarea',this.$embedModal).remove();window.ui_halted=true;this.$embedModalBody.append('<textarea class="raw"></textarea>');$textarea=$('textarea.raw',this.$embedModalBody).val('<script type="text/javascript" src="'+this.model.get('embed_url')+'"></script>');this.$embedModal.modal('show');$textarea.select();},embedFromClick:function(){this.embed();return false;},embedClose:function(){$('textarea',this.$embedModal).remove();},expand:function(){this.$container.toggleClass('expanded',100);this.$tags.toggleClass('expanded');this.select();return false;},fadeAndRemove:function(){var $toRemove=$(this.el);var $nextSnipt=$toRemove.next('article.snipt');window.$selected=false;$toRemove.fadeOut('fast',function(){$(this).remove();$nextSnipt.trigger('selectSnipt');});return false;},goToAuthor:function(){window.location=this.model.get('user').absolute_url;},guessCodeMirrorLexer:function(val){if(val==='html'){return'htmlmixed';}
if(val==='js')return'javascript';if(val==='rb')return'ruby';return val;},favoriteToggle:function(){var that=this;if(this.$el.hasClass('favorited')){$.ajax('/api/private/favorite/'+this.model.get('favorite_id')+'/',{type:'delete',success:function(){that.$el.removeClass('favorited');that.$favorite.text('Favorite');},headers:{'Authorization':'ApiKey '+window.user+':'+window.api_key}});}else{$.ajax('/api/private/favorite/',{data:'{"snipt": '+this.model.get('id')+'}',contentType:'application/json',type:'post',success:function(resp){that.$el.addClass('favorited');that.model.set({'favorite_id':resp.id},{'silent':true});that.$favorite.text('Favorited');},headers:{'Authorization':'ApiKey '+window.user+':'+window.api_key}});}
return false;},initLineNumbers:function(){var lines=$('span.special',this.$el);var that=this;$.each(lines,function(){var l=$(this);var num=l.text().trim();var url=that.model.get('absolute_url');l.replaceWith('<a href="'+url+'#line-'+num+'">'+num+'</a>');});},initLocalVars:function(){this.$aside=$('aside',this.$el);this.$container=$('div.container',this.$el);this.$copyModal=$('div.copy-modal',this.$el);this.$copyModalBody=$('div.modal-body',this.$copyModal);this.$embedModal=$('div.embed-modal',this.$el);this.$embedModalBody=$('div.modal-body',this.$embedModal);this.$favorite=$('a.favorite',this.$el);this.$h1=$('header h1 a',this.$el);this.$tags=$('section.tags ul',this.$aside);this.$copyModal.on('hidden',function(e){$(this).parent().trigger('copyClose');window.ui_halted=false;window.from_modal=true;});this.$embedModal.on('hidden',function(e){$(this).parent().trigger('embedClose');window.ui_halted=false;window.from_modal=true;});},next:function(){if(!window.ui_halted){nextSnipt=this.$el.next('article.snipt');if(nextSnipt.length){return nextSnipt.trigger('selectSnipt');}}},prev:function(){if(!window.ui_halted){prevSnipt=this.$el.prev('article.snipt');if(prevSnipt.length){return prevSnipt.trigger('selectSnipt');}}},remove:function(){return false;},render:function(){this.$el.html(this.template({snipt:this.model.toSafe()}));this.initLocalVars();this.initLineNumbers();if(this.model.get('blog_post')===true){this.$el.addClass('blog-post');}else{this.$el.removeClass('blog-post');}
@ -10,7 +12,8 @@ if(this.model.get('public')===true){this.$el.removeClass('private-snipt');}else{
if(this.model.get('user').username===window.user){this.$el.addClass('editable');}else{this.$el.removeClass('editable');}
if(this.model.get('line_count')>8&&!window.detail){this.$el.addClass('expandable');}else{this.$el.removeClass('expandable');}
$('script#disqus').remove();window.site.$body.append('<script id="disqus" type="text/javascript">'+$('script#disqus-template').text()+'</script>');if(this.$el.attr('id')==='new-snipt'){this.$el.fadeIn('fast');this.$el.attr('id','snipt-'+this.model.get('id'));}
return this;},save:function(){$('button.save, button.save-and-close, button.delete, button.cancel',window.site.$main_edit).attr('disabled','disabled');that.model.save({'title':$('input#snipt_title').val(),'tags':$('label.tags textarea').val(),'tags_list':$('label.tags textarea').val(),'lexer':$('select[name="lexer"]').val(),'lexer_name':$('select[name="lexer"] option:selected').text(),'code':window.editor.getValue(),'blog_post':$('label.blog-post input').is(':checked'),'publish_date':$('label.publish-date input').val(),'public':$('label.public input').is(':checked')},{success:function(model,response){$('button.save, button.save-and-close, button.delete, button.cancel',window.site.$main_edit).removeAttr('disabled');},error:function(model,response){alert('There was a problem saving your snipt. We\'ve been notified. Sorry about that!');}});},select:function(fromClick){$('article.selected',window.site.snipt_list.$el).removeClass('selected');this.$el.addClass('selected');if(fromClick!==true){if(window.site.$snipts.index(this.$el)===0){window.scrollTo(0,0);}else{window.site.$html_body.animate({scrollTop:this.$el.offset().top-50},0);}}
return this;},save:function(){$('button.save, button.save-and-close, button.delete, button.cancel',window.site.$main_edit).attr('disabled','disabled');var code;if(this.$editorTextarea.is(':visible')){code=this.$editorTextarea.val();}else{code=window.editor.getValue();}
that.model.save({'title':$('input#snipt_title').val(),'tags':$('label.tags textarea').val(),'tags_list':$('label.tags textarea').val(),'lexer':$('select[name="lexer"]').val(),'lexer_name':$('select[name="lexer"] option:selected').text(),'code':code,'blog_post':$('label.blog-post input').is(':checked'),'publish_date':$('label.publish-date input').val(),'public':$('label.public input').is(':checked')},{success:function(model,response){$('button.save, button.save-and-close, button.delete, button.cancel',window.site.$main_edit).removeAttr('disabled');},error:function(model,response){alert('There was a problem saving your snipt. We\'ve been notified. Sorry about that!');}});},select:function(fromClick){$('article.selected',window.site.snipt_list.$el).removeClass('selected');this.$el.addClass('selected');if(fromClick!==true){if(window.site.$snipts.index(this.$el)===0){window.scrollTo(0,0);}else{window.site.$html_body.animate({scrollTop:this.$el.offset().top-50},0);}}
window.$selected=this.$el;},selectFromClick:function(e){this.select(true);e.stopPropagation();window.site.$aside_nav.removeClass('open');}});Snipt.SniptListView=Backbone.View.extend({el:'section#snipts',initialize:function(opts){var that=this;opts.snipts.each(this.addExistingSnipt);this.keyboardShortcuts();var cmd;if(navigator.platform=='MacPPC'||navigator.platform=='MacIntel'){cmd='Cmd';}
else{cmd='Ctrl';}
$('span.cmd-ctrl').text(cmd);$('button#add-snipt').click(function(){that.addNewSnipt();});},addExistingSnipt:function(){var $el=$(this);var $created=$('li.created',$el);var $h1=$('header h1 a',$el);var $public=$('div.public',$el);var $blog_post=$('div.blog-post',$el);var $publish_date=$('div.publish-date',$el);var $user=$('li.author a',$el);var is_public=$public.text()==='True'?true:false;var is_blog_post=$blog_post.text()==='True'?true:false;var tag_lis=$('section.tags li',$el);var tags=[];for(var i=0;i<tag_lis.length;i++){var $tag=$('a',tag_lis.eq(i));tags[i]={name:$tag.text(),absolute_url:$tag.attr('href')};}

View File

@ -29,7 +29,8 @@
</h1>
</header>
<section class="code">
<div id="editor"></div>
<div class="editor"></div>
<textarea class="editor hidden"><% snipt.code %></textarea>
</section>
<div class="ruler top-x"></div>
<div class="ruler bottom-x"></div>
@ -63,6 +64,15 @@
<textarea placeholder='tag-1, "tag 2", tag3, etc.'><%= snipt.tags_list %></textarea>
</label>
</div>
<% if (window.user_is_pro) { %>
<div class="editor-settings">
<label class="lexer"><span>Editor<span></label>
<select name="editor" id="id_editor">
<option value="codemirror" selected="selected">CodeMirror</option>
<option value="textarea">Textarea</option>
</select>
</div>
<% } %>
</aside>
</div>
</article>

View File

@ -358,6 +358,7 @@
{% endif %}
{% if request.user.profile.is_pro %}
window.user_is_pro = true;
window.default_editor = '{{ request.user.profile.get_default_editor_display|lower }}';
{% else %}
window.user_is_pro = false;
{% endif %}