integrate tags plugins
This commit is contained in:
parent
5d526717d6
commit
6977150f04
6 changed files with 212 additions and 0 deletions
2
Gemfile
2
Gemfile
|
@ -21,6 +21,8 @@ gem "git"
|
|||
gem "acts_as_list"
|
||||
gem 'rdiscount'
|
||||
|
||||
gem 'acts-as-taggable-on', '~>2.1.0'
|
||||
|
||||
group :assets do
|
||||
gem 'sass-rails', " ~> 3.1.0"
|
||||
gem 'coffee-rails', "~> 3.1.0"
|
||||
|
|
|
@ -54,6 +54,8 @@ GEM
|
|||
activesupport (= 3.1.0)
|
||||
activesupport (3.1.0)
|
||||
multi_json (~> 1.0)
|
||||
acts-as-taggable-on (2.1.1)
|
||||
rails
|
||||
acts_as_list (0.1.4)
|
||||
addressable (2.2.6)
|
||||
ansi (1.3.0)
|
||||
|
@ -246,6 +248,7 @@ PLATFORMS
|
|||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
acts-as-taggable-on (~> 2.1.0)
|
||||
acts_as_list
|
||||
annotate!
|
||||
autotest
|
||||
|
|
|
@ -9,6 +9,8 @@ class Project < ActiveRecord::Base
|
|||
has_many :notes, :dependent => :destroy
|
||||
has_many :snippets, :dependent => :destroy
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
validates :name,
|
||||
:uniqueness => true,
|
||||
:presence => true,
|
||||
|
|
28
db/migrate/20111101222453_acts_as_taggable_on_migration.rb
Normal file
28
db/migrate/20111101222453_acts_as_taggable_on_migration.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
class ActsAsTaggableOnMigration < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :tags do |t|
|
||||
t.string :name
|
||||
end
|
||||
|
||||
create_table :taggings do |t|
|
||||
t.references :tag
|
||||
|
||||
# You should make sure that the column created is
|
||||
# long enough to store the required class names.
|
||||
t.references :taggable, :polymorphic => true
|
||||
t.references :tagger, :polymorphic => true
|
||||
|
||||
t.string :context
|
||||
|
||||
t.datetime :created_at
|
||||
end
|
||||
|
||||
add_index :taggings, :tag_id
|
||||
add_index :taggings, [:taggable_id, :taggable_type, :context]
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :taggings
|
||||
drop_table :tags
|
||||
end
|
||||
end
|
143
vendor/assets/javascripts/jquery.tagify.js
vendored
Normal file
143
vendor/assets/javascripts/jquery.tagify.js
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
/* Author: Alicia Liu */
|
||||
|
||||
(function ($) {
|
||||
|
||||
$.widget("ui.tagify", {
|
||||
options: {
|
||||
delimiters: [13, 188], // what user can type to complete a tag in char codes: [enter], [comma]
|
||||
outputDelimiter: ',', // delimiter for tags in original input field
|
||||
cssClass: 'tagify-container', // CSS class to style the tagify div and tags, see stylesheet
|
||||
addTagPrompt: 'add tags' // placeholder text
|
||||
},
|
||||
|
||||
_create: function() {
|
||||
var self = this,
|
||||
el = self.element,
|
||||
opts = self.options;
|
||||
|
||||
this.tags = [];
|
||||
|
||||
// hide text field and replace with a div that contains it's own input field for entering tags
|
||||
this.tagInput = $("<input type='text'>")
|
||||
.attr( 'placeholder', opts.addTagPrompt )
|
||||
.keypress( function(e) {
|
||||
var $this = $(this),
|
||||
pressed = e.which;
|
||||
|
||||
for ( i in opts.delimiters ) {
|
||||
|
||||
if (pressed == opts.delimiters[i]) {
|
||||
self.add( $this.val() );
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
})
|
||||
// for some reason, in Safari, backspace is only recognized on keyup
|
||||
.keyup( function(e) {
|
||||
var $this = $(this),
|
||||
pressed = e.which;
|
||||
|
||||
// if backspace is hit with no input, remove the last tag
|
||||
if (pressed == 8) { // backspace
|
||||
if ( $this.val() == "" ) {
|
||||
self.remove();
|
||||
return false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
this.tagDiv = $("<div></div>")
|
||||
.addClass( opts.cssClass )
|
||||
.click( function() {
|
||||
$(this).children('input').focus();
|
||||
})
|
||||
.append( this.tagInput )
|
||||
.insertAfter( el.hide() );
|
||||
|
||||
// if the field isn't empty, parse the field for tags, and prepopulate existing tags
|
||||
var initVal = $.trim( el.val() );
|
||||
|
||||
if ( initVal ) {
|
||||
var initTags = initVal.split( opts.outputDelimiter );
|
||||
$.each( initTags, function(i, tag) {
|
||||
self.add( tag );
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_setOption: function( key, value ) {
|
||||
options.key = value;
|
||||
},
|
||||
|
||||
// add a tag, public function
|
||||
add: function(text) {
|
||||
var self = this;
|
||||
text = text || self.tagInput.val();
|
||||
if (text) {
|
||||
var tagIndex = self.tags.length;
|
||||
|
||||
var removeButton = $("<a href='#'>x</a>")
|
||||
.click( function() {
|
||||
self.remove( tagIndex );
|
||||
return false;
|
||||
});
|
||||
var newTag = $("<span></span>")
|
||||
.text( text )
|
||||
.append( removeButton );
|
||||
|
||||
self.tagInput.before( newTag );
|
||||
self.tags.push( text );
|
||||
self.tagInput.val('');
|
||||
}
|
||||
},
|
||||
|
||||
// remove a tag by index, public function
|
||||
// if index is blank, remove the last tag
|
||||
remove: function( tagIndex ) {
|
||||
var self = this;
|
||||
if ( tagIndex == null || tagIndex === (self.tags.length - 1) ) {
|
||||
this.tagDiv.children("span").last().remove();
|
||||
self.tags.pop();
|
||||
}
|
||||
if ( typeof(tagIndex) == 'number' ) {
|
||||
// otherwise just hide this tag, and we don't mess up the index
|
||||
this.tagDiv.children( "span:eq(" + tagIndex + ")" ).hide();
|
||||
// we rely on the serialize function to remove null values
|
||||
delete( self.tags[tagIndex] );
|
||||
}
|
||||
},
|
||||
|
||||
// serialize the tags with the given delimiter, and write it back into the tagified field
|
||||
serialize: function() {
|
||||
var self = this;
|
||||
var delim = self.options.outputDelimiter;
|
||||
var tagsStr = self.tags.join( delim );
|
||||
|
||||
// our tags might have deleted entries, remove them here
|
||||
var dupes = new RegExp(delim + delim + '+', 'g'); // regex: /,,+/g
|
||||
var ends = new RegExp('^' + delim + '|' + delim + '$', 'g'); // regex: /^,|,$/g
|
||||
var outputStr = tagsStr.replace( dupes, delim ).replace(ends, '');
|
||||
|
||||
self.element.val(outputStr);
|
||||
return outputStr;
|
||||
},
|
||||
|
||||
inputField: function() {
|
||||
return this.tagInput;
|
||||
},
|
||||
|
||||
containerDiv: function() {
|
||||
return this.tagDiv;
|
||||
},
|
||||
|
||||
// remove the div, and show original input
|
||||
destroy: function() {
|
||||
$.Widget.prototype.destroy.apply(this);
|
||||
this.tagDiv.remove();
|
||||
this.element.show();
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
34
vendor/assets/stylesheets/jquery-ui/jquery.tagify.css
vendored
Normal file
34
vendor/assets/stylesheets/jquery-ui/jquery.tagify.css
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Tagify styles
|
||||
Author: Alicia Liu test
|
||||
*/
|
||||
|
||||
.tagify-container {
|
||||
}
|
||||
|
||||
.tagify-container > span {
|
||||
display: inline-block;
|
||||
padding: 8px 11px 8px 11px;
|
||||
margin: 1px 5px 0px 0px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #d0e1ff;
|
||||
background-color: #d0e1ff;
|
||||
color: #0f326d;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tagify-container > span > a {
|
||||
padding-left: 5px !important;
|
||||
color: #83a5e1;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tagify-container > input {
|
||||
border: 0 none;
|
||||
width: 100px !important;
|
||||
}
|
||||
|
||||
.tagify-container > input:focus {
|
||||
outline: none;
|
||||
}
|
Loading…
Reference in a new issue