2
0
mirror of https://github.com/moebooru/moebooru synced 2025-08-22 09:57:31 +00:00

Migrate related_tags to jquery.

Now with more coffeescript since debugging is now fun.
Many thanks to coffee-rails-source-maps and related projects.
This commit is contained in:
edogawaconan 2014-03-17 01:32:44 +09:00
parent 649403948e
commit 2bea765b5e
10 changed files with 173 additions and 184 deletions

View File

@ -2,11 +2,14 @@ source "https://rubygems.org"
gem "rails", "~> 4.0.0"
gem "rails-observers"
gem "coffee-rails", "~> 4.0.0"
gem "coffee-rails-source-maps", :group => :development
gem "jquery-rails"
gem "jquery-ui-rails"
gem "uglifier"
gem "sass-rails"
gem "uglifier"
gem "jquery-ui-rails"
gem "pg", :platforms => [:ruby, :mswin, :mingw]
gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.0.rc1", :platforms => :jruby

View File

@ -42,6 +42,15 @@ GEM
cache_digests (0.3.1)
actionpack (>= 3.2)
thread_safe
coffee-rails (4.0.1)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0)
coffee-rails-source-maps (1.4.0)
coffee-script-source (>= 1.6.1)
coffee-script (2.2.0)
coffee-script-source
execjs
coffee-script-source (1.7.0)
daemons (1.1.9)
dalli (2.7.0)
diff-lcs (1.2.5)
@ -178,6 +187,8 @@ DEPENDENCIES
acts_as_versioned_rails3
addressable
cache_digests
coffee-rails (~> 4.0.0)
coffee-rails-source-maps
daemons
dalli
diff-lcs

View File

@ -0,0 +1,4 @@
#= require moebooru
#= require moebooru/related_tags
jQuery(document).ready ->
Moebooru.relatedTags.initialize()

View File

@ -0,0 +1,121 @@
#= require moebooru
jQuery(document).ready ($) ->
window.Moebooru.relatedTags =
recentTags: -> $.cookie("recent_tags").match(/\S+/g) || []
myTags: -> $.cookie("my_tags").match(/\S+/g) || []
artistSource: -> $("#post_source").val()
source: -> $ "#post_tags"
target: -> $ "#related"
tagUrl: (tag) -> Moebooru.path "/post?tags=#{encodeURIComponent tag}"
getTags: ->
source = @source()
selectFrom = source[0].selectionStart
selectTo = source[0].selectionEnd
tags = source.val()
if tags.length != 0 && selectFrom != 0 && selectFrom != tags.length
selectionStart = tags.slice(0, selectFrom).lastIndexOf " "
selectionEnd = tags.indexOf " ", selectTo
selectionStart = 0 if selectionStart == -1
selectionEnd = undefined if selectionEnd == -1
tags = tags.slice selectionStart, selectionEnd
tags
refreshList: (extra) ->
buf = @target().empty()
if @myTags().length > 0
buf.append @buildList("My Tags", @myTags())
if @recentTags().length > 0
buf.append @buildList("Recent Tags", @recentTags())
for title, tags of extra
buf.append @buildList(title, tags) if tags.length > 0
@highlightList()
highlightList: ->
highlightedTags = @source().val().match(/\S+/g) || []
$(".tag-column").find("a").removeClass "highlighted"
for tag in highlightedTags
$(".tag-column").find("a[href='#{@tagUrl tag}']").addClass "highlighted"
buildList: (title, tags) ->
buf = $("<div>").addClass "tag-column"
buf.append $("<h6>").text(title.replace /_/g, " ")
tagsList = $("<ul>")
for tag in tags.sort()
tagName = tag.replace /_/g, " "
tag = tag
tagsList.append(
$("<li>").append $("<a>").text(tagName).attr(href: @tagUrl(tag))
)
buf.append tagsList
fetchStart: -> @target().html $("<em>").text("Fetching...")
fetchArtistSuccess: (data) ->
console.log (artist.name for artist in data)
@refreshList "Artist": (artist.name for artist in data)
fetchSuccess: (data) ->
tagsCollection = {}
for name, tags of data
tagsCollection[name] = (tag[0] for tag in tags)
@refreshList tagsCollection
toggleTag: (e) ->
e.preventDefault()
tagName = $(e.target).text().replace /\s/g, "_"
currentTags = @source().val()
jumpToEnd = @source()[0].selectionStart == currentTags.length
if $(e.target).hasClass "highlighted"
newVal = currentTags.replace(tagName, "")
else
newVal = "#{currentTags} #{tagName}"
newVal = "#{newVal.replace(/^\s+|\s+$/g, "").replace(/\s\s+/g, " ")} "
newVal = "" if newVal == " "
@source().val(newVal)
@source()[0].selectionStart = newVal.length if jumpToEnd
@highlightList()
@source().focus()
run: (e) ->
e.preventDefault()
tags = @getTags()
type = $(e.target).data("type")
if type == "artist-url"
source = @artistSource() || ""
return unless source.length > 0 && source.match /^https?:\/\//
@fetchStart()
$.ajax
url: Moebooru.path "/artist.json"
data:
url: source
limit: 10
success: $.proxy @fetchArtistSuccess, this
else
type = null if type == "all"
return unless tags.length > 0
@fetchStart()
$.ajax
url: Moebooru.path "/tag/related.json"
data: { type: type, tags: tags }
success: $.proxy @fetchSuccess, this
initialize: ->
return unless @source().length && @target().length
$("[data-toggle='related-tags']").click $.proxy(@run, this)
@target().on "click", "a", $.proxy(@toggleTag, this)
@source().on "input keyup", $.proxy(@highlightList, this)
if @artistSource()
$("[data-toggle='related-tags'][data-type='artist-url']").click()
else
@refreshList()

View File

@ -0,0 +1,18 @@
.tag-column {
h6 {
font-style: italic;
}
ul {
list-style: none;
li {
margin: 0;
a.highlighted {
color: white;
background: rgb(0, 111, 250);
}
}
}
}

View File

@ -123,7 +123,7 @@ class TagController < ApplicationController
end
def related
if params[:type]
if params[:type].present?
@tags = Tag.scan_tags(params[:tags])
@tags = TagAlias.to_aliased(@tags)
@tags = @tags.inject({}) do |all, x|

View File

@ -43,8 +43,6 @@
<% content_for :post_cookie_javascripts do %>
<script type="text/javascript">
RelatedTags.init(Cookie.get('my_tags'), '<%= params[:url] %>')
if (Cookie.get('resize_image') == '1') {
Post.resize_image()
}

View File

@ -62,12 +62,13 @@
<td>
<%= text_area "post", "tags", :readonly => !@post.can_be_seen_by?(@current_user), :size => "50x4", :value => @post.cached_tags, :tabindex => 10 %>
<% if @post.can_be_seen_by?(@current_user) %>
<%= link_to_function t('.related.tags'), "RelatedTags.find('post_tags')" %> |
<%= link_to_function t('.related.artists'), "RelatedTags.find('post_tags', 'artist')" %> |
<%= link_to_function t('.related.characters'), "RelatedTags.find('post_tags', 'char')" %> |
<%= link_to_function t('.related.copyrights'), "RelatedTags.find('post_tags', 'copyright')" %>
<%= link_to t(".related.tags"), "#", :data => { :toggle => "related-tags", :type => "all" } %> |
<%= link_to t(".related.artists"), "#", :data => { :toggle => "related-tags", :type => "artist" } %> |
<%= link_to t(".related.characters"), "#", :data => { :toggle => "related-tags", :type => "char" } %> |
<%= link_to t(".related.copyrights"), "#", :data => { :toggle => "related-tags", :type => "copyright" } %> |
<%= link_to t("post.upload.form.find_related.circles"), "#", :data => { :toggle => "related-tags", :type => "circle" } %>
<% if CONFIG["enable_artists"] %>
| <%= link_to_function(t('.find_artists'), "RelatedTags.find_artist($F('post_source'))") %>
| <%= link_to t(".find_artists"), "#", :data => { :toggle => "related-tags", :type => "artist-url" } %>
<% end %>
<% end %>
</td>

View File

@ -79,9 +79,9 @@
<% end %>
</th>
<td>
<%= text_field "post", "source", :value => params["url"], :size => 50, :tabindex => 2 %>
<%= text_field "post", "source", :value => (params["url"] || params["ref"]), :size => 50, :tabindex => 2 %>
<% if CONFIG["enable_artists"] %>
<%= link_to_function(t('.form.find_artist'), "RelatedTags.find_artist($F('post_source'))") %>
<%= link_to t(".form.find_artist"), "#", :data => { :toggle => "related-tags", :type => "artist-url" } %>
<% end %>
</td>
</tr>
@ -94,11 +94,11 @@
</th>
<td>
<%= text_area "post", "tags", :value => params[:tags], :size => "60x2", :tabindex => 3 %>
<%= link_to_function t('.form.find_related.tags'), "RelatedTags.find('post_tags')" %> |
<%= link_to_function t('.form.find_related.artists'), "RelatedTags.find('post_tags', 'artist')" %> |
<%= link_to_function t('.form.find_related.characters'), "RelatedTags.find('post_tags', 'char')" %> |
<%= link_to_function t('.form.find_related.copyrights'), "RelatedTags.find('post_tags', 'copyright')" %> |
<%= link_to_function t('.form.find_related.circles'), "RelatedTags.find('post_tags', 'circle')" %>
<%= link_to t(".form.find_related.tags"), "#", :data => { :toggle => "related-tags", :type => "all" } %> |
<%= link_to t(".form.find_related.artists"), "#", :data => { :toggle => "related-tags", :type => "artist" } %> |
<%= link_to t(".form.find_related.characters"), "#", :data => { :toggle => "related-tags", :type => "char" } %> |
<%= link_to t(".form.find_related.copyrights"), "#", :data => { :toggle => "related-tags", :type => "copyright" } %> |
<%= link_to t(".form.find_related.circles"), "#", :data => { :toggle => "related-tags", :type => "circle" } %>
</td>
</tr>
<% if CONFIG["enable_parent_posts"] %>
@ -160,12 +160,6 @@
}.bindAsEventListener());
</script>
<% content_for :post_cookie_javascripts do %>
<script type="text/javascript">
RelatedTags.init(Cookie.unescape(Cookie.get('my_tags')), '<%= params[:ref] || params[:url] %>')
</script>
<% end %>
<script type="text/javascript">
new TagCompletionBox($("post_tags"));
if(TagCompletion)

View File

@ -1,161 +0,0 @@
RelatedTags = {
user_tags: [],
recent_tags: [],
recent_search: {},
init: function(user_tags, artist_url) {
this.user_tags = (user_tags.match(/\S+/g) || []).sort()
this.recent_tags = Cookie.get("recent_tags").match(/\S+/g)
if (this.recent_tags) {
this.recent_tags = this.recent_tags.sort().uniq(true)
} else {
this.recent_tags = []
}
if ((artist_url != null) && (artist_url.match(/^http/))) {
this.find_artist($F("post_source"))
} else {
this.build_all({})
}
},
toggle: function(link, field) {
var field = $(field)
var tags = field.value.match(/\S+/g) || []
var tag = (link.innerText || link.textContent).replace(/ /g, "_")
if (tags.include(tag)) {
field.value = tags.without(tag).join(" ") + " "
} else {
field.value = tags.concat([tag]).join(" ") + " "
}
this.build_all(this.recent_search)
return false
},
build_html: function(key, tags) {
if (tags == null || tags.size() == 0) {
return ""
}
var html = ""
var current = $F("post_tags").match(/\S+/g) || []
html += '<div class="tag-column">'
html += '<h6><em>' + key.replace(/_/g, " ") + '</em></h6>'
for (var i=0; i<tags.size(); ++i) {
var tag = tags[i]
html += ('<a href="/post?tags=' + encodeURIComponent(tag) + '" onclick="RelatedTags.toggle(this, \'post_tags\'); return false"')
if (current.include(tag)) {
html += ' style="background: rgb(0, 111, 250); color: white;"'
}
html += '>' + tag.escapeHTML().replace(/_/g, " ") + '</a><br> '
}
html += '</div>'
return html
},
build_all: function(tags) {
this.recent_search = tags
var html = this.build_html("My Tags", this.user_tags) + this.build_html("Recent Tags", this.recent_tags)
var keys = []
for (key in tags) {
keys.push(key)
}
keys.sort()
for (var i=0; i<keys.size(); ++i) {
html += this.build_html(keys[i], tags[keys[i]])
}
$("related").update(html)
},
find: function(field, type) {
$("related").update("<em>Fetching...</em>")
var field = $(field)
var tags = null
// .textLength is empty in IE9.
if (field.textLength == null) {
field.textLength = jQuery(field).val().length;
};
// Fetch all related tags if cursor position is either at the beginning or
// the end of text area.
if ((field.selectionStart == 0) || (field.selectionStart == field.textLength)) {
tags = field.value
} else {
var a = field.selectionStart
var b = field.selectionEnd
if(a != b) {
while ((b > 0) && field.value[b] != " ") {
b -= 1
}
}
while ((a > 0) && field.value[a] != " ") {
a -= 1
}
if (field.value[a] == " ") {
a += 1
}
while ((b < field.textLength) && field.value[b] != " ") {
b += 1
}
tags = field.value.slice(a, b)
}
var params = {"tags": tags}
if (type) {
params["type"] = type
}
new Ajax.Request("/tag/related.json", {
method: 'get',
parameters: params,
onComplete: function(resp) {
var resp = resp.responseJSON
var converted = this.convert_related_js_response(resp)
this.build_all(converted)
}.bind(this)
})
},
convert_related_js_response: function(resp) {
var converted = {}
for (k in resp) {
var tags = resp[k].map(function(x) {return x[0]}).sort()
converted[k] = tags
}
return converted
},
find_artist: function(url) {
if (url.match(/^http/)) {
new Ajax.Request("/artist.json", {
method: "get",
parameters: {
"url": url,
"limit": "10"
},
onComplete: function(resp) {
var resp = resp.responseJSON
this.build_all({"Artist": resp.map(function(x) {return x.name})})
}.bind(this)
})
}
}
}