mirror of
https://github.com/moebooru/moebooru
synced 2025-08-28 20:47:42 +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:
parent
649403948e
commit
2bea765b5e
7
Gemfile
7
Gemfile
@ -2,11 +2,14 @@ source "https://rubygems.org"
|
|||||||
|
|
||||||
gem "rails", "~> 4.0.0"
|
gem "rails", "~> 4.0.0"
|
||||||
gem "rails-observers"
|
gem "rails-observers"
|
||||||
|
|
||||||
|
gem "coffee-rails", "~> 4.0.0"
|
||||||
|
gem "coffee-rails-source-maps", :group => :development
|
||||||
gem "jquery-rails"
|
gem "jquery-rails"
|
||||||
|
gem "jquery-ui-rails"
|
||||||
|
gem "uglifier"
|
||||||
|
|
||||||
gem "sass-rails"
|
gem "sass-rails"
|
||||||
gem "uglifier"
|
|
||||||
gem "jquery-ui-rails"
|
|
||||||
|
|
||||||
gem "pg", :platforms => [:ruby, :mswin, :mingw]
|
gem "pg", :platforms => [:ruby, :mswin, :mingw]
|
||||||
gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.0.rc1", :platforms => :jruby
|
gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.0.rc1", :platforms => :jruby
|
||||||
|
11
Gemfile.lock
11
Gemfile.lock
@ -42,6 +42,15 @@ GEM
|
|||||||
cache_digests (0.3.1)
|
cache_digests (0.3.1)
|
||||||
actionpack (>= 3.2)
|
actionpack (>= 3.2)
|
||||||
thread_safe
|
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)
|
daemons (1.1.9)
|
||||||
dalli (2.7.0)
|
dalli (2.7.0)
|
||||||
diff-lcs (1.2.5)
|
diff-lcs (1.2.5)
|
||||||
@ -178,6 +187,8 @@ DEPENDENCIES
|
|||||||
acts_as_versioned_rails3
|
acts_as_versioned_rails3
|
||||||
addressable
|
addressable
|
||||||
cache_digests
|
cache_digests
|
||||||
|
coffee-rails (~> 4.0.0)
|
||||||
|
coffee-rails-source-maps
|
||||||
daemons
|
daemons
|
||||||
dalli
|
dalli
|
||||||
diff-lcs
|
diff-lcs
|
||||||
|
4
app/assets/javascripts/boot.js.coffee
Normal file
4
app/assets/javascripts/boot.js.coffee
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#= require moebooru
|
||||||
|
#= require moebooru/related_tags
|
||||||
|
jQuery(document).ready ->
|
||||||
|
Moebooru.relatedTags.initialize()
|
121
app/assets/javascripts/moebooru/related_tags.js.coffee
Normal file
121
app/assets/javascripts/moebooru/related_tags.js.coffee
Normal 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()
|
18
app/assets/stylesheets/related_tags.css.scss
Normal file
18
app/assets/stylesheets/related_tags.css.scss
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -123,7 +123,7 @@ class TagController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def related
|
def related
|
||||||
if params[:type]
|
if params[:type].present?
|
||||||
@tags = Tag.scan_tags(params[:tags])
|
@tags = Tag.scan_tags(params[:tags])
|
||||||
@tags = TagAlias.to_aliased(@tags)
|
@tags = TagAlias.to_aliased(@tags)
|
||||||
@tags = @tags.inject({}) do |all, x|
|
@tags = @tags.inject({}) do |all, x|
|
||||||
|
@ -43,8 +43,6 @@
|
|||||||
<% content_for :post_cookie_javascripts do %>
|
<% content_for :post_cookie_javascripts do %>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
RelatedTags.init(Cookie.get('my_tags'), '<%= params[:url] %>')
|
|
||||||
|
|
||||||
if (Cookie.get('resize_image') == '1') {
|
if (Cookie.get('resize_image') == '1') {
|
||||||
Post.resize_image()
|
Post.resize_image()
|
||||||
}
|
}
|
||||||
|
@ -62,12 +62,13 @@
|
|||||||
<td>
|
<td>
|
||||||
<%= text_area "post", "tags", :readonly => !@post.can_be_seen_by?(@current_user), :size => "50x4", :value => @post.cached_tags, :tabindex => 10 %>
|
<%= 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) %>
|
<% if @post.can_be_seen_by?(@current_user) %>
|
||||||
<%= link_to_function t('.related.tags'), "RelatedTags.find('post_tags')" %> |
|
<%= link_to t(".related.tags"), "#", :data => { :toggle => "related-tags", :type => "all" } %> |
|
||||||
<%= link_to_function t('.related.artists'), "RelatedTags.find('post_tags', 'artist')" %> |
|
<%= link_to t(".related.artists"), "#", :data => { :toggle => "related-tags", :type => "artist" } %> |
|
||||||
<%= link_to_function t('.related.characters'), "RelatedTags.find('post_tags', 'char')" %> |
|
<%= link_to t(".related.characters"), "#", :data => { :toggle => "related-tags", :type => "char" } %> |
|
||||||
<%= link_to_function t('.related.copyrights'), "RelatedTags.find('post_tags', 'copyright')" %>
|
<%= 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"] %>
|
<% 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 %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
|
@ -79,9 +79,9 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<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"] %>
|
<% 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 %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -94,11 +94,11 @@
|
|||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<%= text_area "post", "tags", :value => params[:tags], :size => "60x2", :tabindex => 3 %>
|
<%= 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 t(".form.find_related.tags"), "#", :data => { :toggle => "related-tags", :type => "all" } %> |
|
||||||
<%= link_to_function t('.form.find_related.artists'), "RelatedTags.find('post_tags', 'artist')" %> |
|
<%= link_to t(".form.find_related.artists"), "#", :data => { :toggle => "related-tags", :type => "artist" } %> |
|
||||||
<%= link_to_function t('.form.find_related.characters'), "RelatedTags.find('post_tags', 'char')" %> |
|
<%= link_to t(".form.find_related.characters"), "#", :data => { :toggle => "related-tags", :type => "char" } %> |
|
||||||
<%= link_to_function t('.form.find_related.copyrights'), "RelatedTags.find('post_tags', 'copyright')" %> |
|
<%= link_to t(".form.find_related.copyrights"), "#", :data => { :toggle => "related-tags", :type => "copyright" } %> |
|
||||||
<%= link_to_function t('.form.find_related.circles'), "RelatedTags.find('post_tags', 'circle')" %>
|
<%= link_to t(".form.find_related.circles"), "#", :data => { :toggle => "related-tags", :type => "circle" } %>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% if CONFIG["enable_parent_posts"] %>
|
<% if CONFIG["enable_parent_posts"] %>
|
||||||
@ -160,12 +160,6 @@
|
|||||||
}.bindAsEventListener());
|
}.bindAsEventListener());
|
||||||
</script>
|
</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">
|
<script type="text/javascript">
|
||||||
new TagCompletionBox($("post_tags"));
|
new TagCompletionBox($("post_tags"));
|
||||||
if(TagCompletion)
|
if(TagCompletion)
|
||||||
|
@ -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)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user