meshcomplete 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in meshcomplete.gemspec
4
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,10 @@
1
+ = Meshcomplete
2
+
3
+ # add "gem 'meshcomplete'" to Gemfile
4
+ $ bundle install
5
+ $ rails g meshcomplete # creates migration file, Subject & Synonym model, JavaScript & CSS files
6
+ $ rake db:migrate
7
+ $ rake meshcomplete:load_data
8
+
9
+ # add to config/routes.rb
10
+ match 'meshcomplete-update' => 'genes#top' # change to appropriate controller & method
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,6 @@
1
+ class MeshcompleteController < ApplicationController
2
+ def search
3
+ items = Synonym.search(params[:term])
4
+ render :json => items
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ class Subject < ActiveRecord::Base
2
+ has_many :synonyms
3
+ end
@@ -0,0 +1,8 @@
1
+ class Synonym < ActiveRecord::Base
2
+ belongs_to :subject
3
+
4
+ def self.search(starts_with, limit = 10)
5
+ mesh = where(["term LIKE ?", "#{starts_with}%"]).limit(limit).order("term asc").includes(:subject).group_by(&:subject)
6
+ mesh.keys.compact.sort_by(&:term).map {|m| {"id" => m.id, "label" => m.term, "value" => m.term, "entries" => mesh[m].reject {|e| m.term == e.term}.map{|e| e.term}.sort}}
7
+ end
8
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ Rails.application.routes.draw do
2
+ mount_at = Meshcomplete::Engine.config.mount_at
3
+ match mount_at + "meshcomplete" => "meshcomplete/meshcomplete#search"
4
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Creates auto-complete search box for MeSH.
3
+
4
+ Example:
5
+ rails generate meshcomplete Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,32 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ class MeshcompleteGenerator < Rails::Generators::Base
5
+ include Rails::Generators::Migration
6
+
7
+ source_root File.expand_path('../templates', __FILE__)
8
+
9
+ def self.next_migration_number(dirname)
10
+ if ActiveRecord::Base.timestamped_migrations
11
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
12
+ else
13
+ "%.3d" % (current_migration_number(dirname) + 1)
14
+ end
15
+ end
16
+
17
+ def create_subjects_migration_file
18
+ migration_template 'create_subjects.rb', 'db/migrate/create_subjects.rb'
19
+ end
20
+
21
+ def create_synonyms_migration_file
22
+ migration_template 'create_synonyms.rb', 'db/migrate/create_synonyms.rb'
23
+ end
24
+
25
+ def copy_stylesheets
26
+ copy_file 'meshcomplete.css', 'public/stylesheets/meshcomplete.css'
27
+ end
28
+
29
+ def copy_javascripts
30
+ copy_file 'meshcomplete.js', 'public/javascripts/meshcomplete.js'
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ class CreateSubjects < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :subjects do |t|
4
+ t.string :term
5
+ end
6
+ add_index :subjects, :term
7
+ end
8
+
9
+ def self.down
10
+ drop_table :subjects
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ class CreateSynonyms < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :synonyms do |t|
4
+ t.integer :subject_id
5
+ t.string :term
6
+ end
7
+ add_index :synonyms, :subject_id
8
+ add_index :synonyms, :term
9
+ end
10
+
11
+ def self.down
12
+ drop_table :synonyms
13
+ end
14
+ end
@@ -0,0 +1,85 @@
1
+ #meshcomplete-box {
2
+ width: 90%;
3
+ margin: 1em;
4
+ padding: 0.25em 0.25em 0 0.25em;
5
+ border:1px solid #aaa;
6
+ background-color:#fff;
7
+ cursor:text;
8
+ display: block;
9
+ }
10
+ #meshcomplete {
11
+ margin: 0 0 0.25em 0;
12
+ padding: 0;
13
+ border: none;
14
+ display: inline-block;
15
+ font-size: 1em;
16
+ cursor:text;
17
+ }
18
+ #meshcomplete:focus {
19
+ outline-width: 0;
20
+ }
21
+ #meshcomplete-box .selected {
22
+ display:inline-block;
23
+ margin: 0 0.25em 0.25em 0;
24
+ padding: 0 0.25em;
25
+ background-color: #eee;
26
+ border: 1px solid #999;
27
+ -moz-border-radius: 4px;
28
+ -webkit-border-radius: 4px;
29
+ border-radius: 4px;
30
+ color:#333;
31
+ font-size: 1em;
32
+ }
33
+ #meshcomplete-box .operator {
34
+ display:inline-block;
35
+ margin: 0 0.4em 0 0;
36
+ padding: 0 0.25em;
37
+ background-color: #eee;
38
+ border: 1px solid #999;
39
+ -moz-border-radius: 4px;
40
+ -webkit-border-radius: 4px;
41
+ border-radius: 4px;
42
+ color:#999;
43
+ font-size: 0.75em;
44
+ text-align: center;
45
+ cursor: pointer;
46
+ width: 2.5em;
47
+ }
48
+ #meshcomplete-box .operator:hover {
49
+ color: #333;
50
+ }
51
+ #meshcomplete-box .remove {
52
+ display: inline-block;
53
+ margin: 0 0 0 0.25em;
54
+ padding: 0;
55
+ color: #999;
56
+ text-decoration: none;
57
+ font-weight: bold;
58
+ }
59
+ #meshcomplete-box .remove:hover {
60
+ background-color: #eee;
61
+ color: #333;
62
+ }
63
+ #meshcomplete-clear {
64
+ float: right;
65
+ cursor: pointer;
66
+ font-weight: bold;
67
+ color: #999;
68
+ }
69
+ #meshcomplete-clear:hover {
70
+ color: #333;
71
+ }
72
+ .ui-autocomplete {
73
+ width: 20em;
74
+ }
75
+ .ui-menu-item .entry_term {
76
+ font-size: 0.75em;
77
+ color: #999;
78
+ }
79
+ .ui-menu-item .matched {
80
+ font-weight: bold;
81
+ }
82
+ .ui-autocomplete li {
83
+ list-style: none;
84
+ text-align: left;
85
+ }
@@ -0,0 +1,89 @@
1
+ $(function() {
2
+ $("#meshcomplete").attr("value","").attr("size", 5);
3
+ $("#meshcomplete-box").click(function(){
4
+ $("#meshcomplete").focus();
5
+ });
6
+ $("#meshcomplete-box .remove").live("click", function(){
7
+ var removed_id = $(this).parent().attr("data-meshcomplete-id");
8
+ var selected_ids = $("#meshcomplete-selected-ids").attr("value");
9
+ selected_ids = selected_ids.replace(new RegExp("," + removed_id), "");
10
+ $("#meshcomplete-selected-ids").attr("value", selected_ids);
11
+ $(this).parent().remove();
12
+ if ($("#meshcomplete-box .operator").length >= $("#meshcomplete-box .selected").length) {
13
+ $("#meshcomplete-box .operator").last().remove();
14
+ }
15
+ if ($("#meshcomplete-box .selected").length > 0) {
16
+ $.get("/meshcomplete-update", { ids: selected_ids },
17
+ function(data) {
18
+ $("#meshcomplete-update").html(data);
19
+ }
20
+ );
21
+ } else {
22
+ $("#meshcomplete-update").html("");
23
+ }
24
+ });
25
+ $("#meshcomplete-clear").live("click", function(){
26
+ $("#meshcomplete-box .selected").each(function(index) { $(this).remove() });
27
+ $("#meshcomplete-box .operator").each(function(index) { $(this).remove() });
28
+ $("#meshcomplete-selected-ids").attr("value", "");
29
+ $("#meshcomplete").attr("value", "");
30
+ $("#meshcomplete-update").html("");
31
+ });
32
+ $("#meshcomplete").bind('keyup keydown blur update', function(){
33
+ if($("#meshcomplete").attr("size") < $("#meshcomplete").val().length){
34
+ size = $("#meshcomplete").val().length + 5;
35
+ $("#meshcomplete").attr("size",size);
36
+ }
37
+ });
38
+ $("#meshcomplete").autocomplete({
39
+ source: "/meshcomplete",
40
+ select: function(e, ui) {
41
+ var selected = ui.item.value,
42
+ span = $("<span>").addClass("selected").text(selected).attr("data-meshcomplete-id", ui.item.id);
43
+ if ($("#meshcomplete-box .selected").length > 0) {
44
+ var operator = $("<span>").addClass("operator").attr({
45
+ }).html("AND").toggle(
46
+ function () {
47
+ $(this).html("OR");
48
+ },
49
+ function () {
50
+ $(this).html("NOT");
51
+ },
52
+ function () {
53
+ $(this).html("AND");
54
+ }
55
+ );
56
+ operator.insertBefore("#meshcomplete");
57
+ }
58
+ var a = $("<a>").addClass("remove").attr({
59
+ href: "javascript: return false;",
60
+ title: "Remove " + selected
61
+ }).html("&times;").appendTo(span);
62
+ span.insertBefore("#meshcomplete");
63
+ $("#meshcomplete").attr("value","").attr("size", 5);
64
+ var selected_ids = $("#meshcomplete-selected-ids").attr("value").split(",");
65
+ selected_ids.push( ui.item.id );
66
+ $("#meshcomplete-selected-ids").attr("value", selected_ids.join(","));
67
+ $("#meshcomplete-update").html('<img src="/images/loading.gif"> Loading ...').slideDown("slow");
68
+ $.get("/meshcomplete-update", { ids: selected_ids.join(",") },
69
+ function(data) {
70
+ $("#meshcomplete-update").html(data).slideDown("slow");
71
+ }
72
+ );
73
+ return false;
74
+ },
75
+ focus: function() {
76
+ return false;
77
+ }
78
+ })
79
+ .data( "autocomplete" )._renderItem = function( ul, item ) {
80
+ var re_label = new RegExp("^" + this.term, "i");
81
+ var re_entries = new RegExp("(^|\| )" + this.term, "gi");
82
+ var label = item.label.replace(re_label, "<span class='matched'>$&" + "</span>");
83
+ var entries = item.entries.join(" | ").replace(re_entries, "<span class='matched'>" + "$&" + "</span>");
84
+ return $( "<li></li>" )
85
+ .data( "item.autocomplete", item )
86
+ .append("<a>" + label + "<div class='entry_term'>" + entries + "</div>" + "</a>")
87
+ .appendTo( ul );
88
+ };
89
+ });
@@ -0,0 +1,3 @@
1
+ module Meshcomplete
2
+ require "meshcomplete/engine" if defined?(Rails)
3
+ end
@@ -0,0 +1,10 @@
1
+ module Meshcomplete
2
+ module ActionViewExtension
3
+ extend ActiveSupport::Concern
4
+ module InstanceMethods
5
+ def meshcomplete(ids)
6
+ "<div id=\"meshcomplete-box\"><input id=\"meshcomplete\" /><span id=\"meshcomplete-clear\" title=\"Clear search\">&times;</span><input type=\"hidden\" id=\"meshcomplete-selected-ids\" value=\"#{ids}\"/></div><div id=\"meshcomplete-update\"></div>".html_safe
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ require "meshcomplete"
2
+ require "rails"
3
+ require "meshcomplete/action_view_extension"
4
+
5
+ module Meshcomplete
6
+ class Engine < Rails::Engine
7
+ config.mount_at = '/'
8
+
9
+ initializer "check config" do |app|
10
+ config.mount_at += '/' unless config.mount_at.last == '/'
11
+ end
12
+
13
+ initializer 'meshcomplete' do |app|
14
+ ActiveSupport.on_load(:action_view) do
15
+ ActionView::Base.send :include, Meshcomplete::ActionViewExtension
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module Meshcomplete
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'open-uri'
2
+ namespace :meshcomplete do
3
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "meshcomplete/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "meshcomplete"
7
+ s.version = Meshcomplete::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Joon Lee"]
10
+ s.email = ["seouri@gmail.com"]
11
+ s.homepage = "https://github.com/seouri/meshcomplete"
12
+ s.summary = %q{Meshcomplete is a Ruby on Rails engine for MeSH autocomplete search box built with jQuery UI.}
13
+ s.description = %q{}
14
+
15
+ s.rubyforge_project = "meshcomplete"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ s.add_dependency('jquery-rails', '>= 0.2.7');
22
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: meshcomplete
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Joon Lee
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-16 00:00:00 -04:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: jquery-rails
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 0.2.7
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ description: ""
28
+ email:
29
+ - seouri@gmail.com
30
+ executables: []
31
+
32
+ extensions: []
33
+
34
+ extra_rdoc_files: []
35
+
36
+ files:
37
+ - .gitignore
38
+ - Gemfile
39
+ - README.rdoc
40
+ - Rakefile
41
+ - app/controllers/meshcomplete_controller.rb
42
+ - app/models/subject.rb
43
+ - app/models/synonym.rb
44
+ - config/routes.rb
45
+ - lib/generators/meshcomplete/USAGE
46
+ - lib/generators/meshcomplete/meshcomplete_generator.rb
47
+ - lib/generators/meshcomplete/templates/create_subjects.rb
48
+ - lib/generators/meshcomplete/templates/create_synonyms.rb
49
+ - lib/generators/meshcomplete/templates/meshcomplete.css
50
+ - lib/generators/meshcomplete/templates/meshcomplete.js
51
+ - lib/meshcomplete.rb
52
+ - lib/meshcomplete/action_view_extension.rb
53
+ - lib/meshcomplete/engine.rb
54
+ - lib/meshcomplete/version.rb
55
+ - lib/tasks/meshcomplete.rake
56
+ - meshcomplete.gemspec
57
+ has_rdoc: true
58
+ homepage: https://github.com/seouri/meshcomplete
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options: []
63
+
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project: meshcomplete
81
+ rubygems_version: 1.6.2
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Meshcomplete is a Ruby on Rails engine for MeSH autocomplete search box built with jQuery UI.
85
+ test_files: []
86
+