diff --git a/app/assets/javascripts/blacklists.js b/app/assets/javascripts/blacklists.js index ac8f2cafc..af2320f1b 100644 --- a/app/assets/javascripts/blacklists.js +++ b/app/assets/javascripts/blacklists.js @@ -57,7 +57,7 @@ var link = $(""); var count = $(""); - link.html(entry.tags); + link.text(entry.tags); link.click(Danbooru.Blacklist.toggle_entry); count.html(entry.hits); item.append(link); diff --git a/app/assets/javascripts/common.js b/app/assets/javascripts/common.js index 31b6ce685..19de27ca6 100644 --- a/app/assets/javascripts/common.js +++ b/app/assets/javascripts/common.js @@ -15,6 +15,11 @@ $(function() { Danbooru.Cookie.put('hide_upgrade_account_notice', '1', 7); e.preventDefault(); }); + + $("#close-notice-link").click(function(e) { + $('#notice').fadeOut("fast"); + e.preventDefault(); + }); }); var Danbooru = {}; diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 2d49d888e..2834ad61e 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -89,25 +89,36 @@ Danbooru.Note = { scale: function($note_box) { var $image = $("#image"); - var ratio = $image.width() / parseFloat($("#image").data("original-width")); - var $note = $("#notes > article[data-id=" + $note_box.data("id") + "]"); + var ratio = $image.width() / parseFloat($image.data("original-width")); + var MIN_SIZE = 5; $note_box.css({ - top: Math.ceil(parseFloat($note.data("y")) * ratio), - left: Math.ceil(parseFloat($note.data("x")) * ratio), - width: Math.ceil(parseFloat($note.data("width")) * ratio), - height: Math.ceil(parseFloat($note.data("height")) * ratio) + top: Math.ceil(parseFloat($note_box.data("y")) * ratio), + left: Math.ceil(parseFloat($note_box.data("x")) * ratio), + width: Math.max(MIN_SIZE, Math.ceil(parseFloat($note_box.data("width")) * ratio)), + height: Math.max(MIN_SIZE, Math.ceil(parseFloat($note_box.data("height")) * ratio)) }); Danbooru.Note.Box.resize_inner_border($note_box); }, scale_all: function() { + var container = document.getElementById('note-container'); + // Hide notes while rescaling, to prevent unnecessary reflowing + var was_visible = container.style.display != 'none'; + if (was_visible) container.style.display = 'none'; $(".note-box").each(function(i, v) { Danbooru.Note.Box.scale($(v)); }); + if (was_visible) container.style.display = 'block'; }, toggle_all: function() { - $(".note-box").toggle(); + // Ignore the click event when adding a note + if ((new Date).getTime() < Danbooru.Note.ignore_click_until) { + return; + } + var is_hidden = document.getElementById('note-container').style.display == 'none'; + // Why does toggle() not work here? + $("#note-container").toggle(is_hidden); } }, @@ -158,6 +169,10 @@ Danbooru.Note = { Danbooru.Note.Body.hide_all(); Danbooru.Note.clear_timeouts(); var $note_body = Danbooru.Note.Body.find(id); + if (!$note_body.data('resized')) { + Danbooru.Note.Body.resize($note_body); + $note_body.data('resized', 'true'); + } $note_body.show(); Danbooru.Note.Body.initialize($note_body); }, @@ -212,7 +227,7 @@ Danbooru.Note = { } } while ((hi - lo) > 4) if ($note_body.height() > h) { - $note_body.css("minWidth", hi); + $note_body.css("min-width", hi); } } }, @@ -419,7 +434,6 @@ Danbooru.Note = { Danbooru.Note.TranslationMode.active = true; $("#original-file-link").click(); - $("#image").one("click", function() { $(".note-box").show() }); /* override the 'hide all note boxes' click event */ $("#image").one("mousedown", Danbooru.Note.TranslationMode.Drag.start); $(window).bind("mouseup", Danbooru.Note.TranslationMode.Drag.stop); Danbooru.notice('Click or drag on the image to create a note (shortcut is n)'); @@ -433,17 +447,26 @@ Danbooru.Note = { Danbooru.Note.TranslationMode.active = false; var offset = $("#image").offset(); - if(dragged) { - if(w > 9 && h > 9) { /* minimum note size: 10px */ - Danbooru.Note.new(x-offset.left,y-offset.top,w,h); + if (dragged) { + if (w > 9 || h > 9) { /* minimum note size: 10px */ + if (w <= 9) { + w = 10; + } else if (h <= 9) { + h = 10; + } + Danbooru.Note.new(x - offset.left, y - offset.top, w, h); } } else { Danbooru.Note.new(e.pageX - offset.left, e.pageY - offset.top); } Danbooru.Note.TranslationMode.stop(); - $(".note-box").show(); + $("#note-container").show(); e.stopPropagation(); e.preventDefault(); + + // Hack to ignore clicks for some milliseconds + // The mouseup event is executed before the click event, so it's hard to do this properly + Danbooru.Note.ignore_click_until = (new Date).getTime() + 200; }, Drag: { @@ -506,10 +529,10 @@ Danbooru.Note = { Danbooru.Note.TranslationMode.Drag.h = -Danbooru.Note.TranslationMode.Drag.dragDistanceY; } - $('#note-helper').css({ /* preview of the note you are dragging */ + $('#note-preview').css({ display: 'block', - left: (Danbooru.Note.TranslationMode.Drag.x - offset.left + 1), - top: (Danbooru.Note.TranslationMode.Drag.y - offset.top + 1), + left: (Danbooru.Note.TranslationMode.Drag.x + 1), + top: (Danbooru.Note.TranslationMode.Drag.y + 1), width: (Danbooru.Note.TranslationMode.Drag.w - 3), height: (Danbooru.Note.TranslationMode.Drag.h - 3) }); @@ -523,7 +546,7 @@ Danbooru.Note = { $(window).unbind("mousemove"); if(Danbooru.Note.TranslationMode.Drag.dragging) { - $('#note-helper').css({display:'none'}); + $('#note-preview').css({display:'none'}); Danbooru.Note.TranslationMode.create_note(e, true, Danbooru.Note.TranslationMode.Drag.x, Danbooru.Note.TranslationMode.Drag.y, Danbooru.Note.TranslationMode.Drag.w-1, Danbooru.Note.TranslationMode.Drag.h-1); Danbooru.Note.TranslationMode.Drag.dragging = false; /* border of the note is pixel-perfect on the preview border */ } else { /* no dragging -> create a normal note */ @@ -541,24 +564,21 @@ Danbooru.Note = { editing: false, timeouts: [], pending: {}, + ignore_click_until: 0, - add: function(id, x, y, w, h, text) { + add: function(container, id, x, y, w, h, text) { var $note_box = Danbooru.Note.Box.create(id); var $note_body = Danbooru.Note.Body.create(id); - $note_box.css({ - left: x, - top: y, - width: w, - height: h, - display: 'none' - }); - - $("#note-container").append($note_box); - $("#note-container").append($note_body); + $note_box.data('x', x); + $note_box.data('y', y); + $note_box.data('width', w); + $note_box.data('height', h); + container.appendChild($note_box[0]); + container.appendChild($note_body[0]); $note_body.data("original-body", text); Danbooru.Note.Box.scale($note_box); - Danbooru.Note.Body.set_text($note_body, text); + Danbooru.Note.Body.display_text($note_body, text); }, new: function(x, y, w, h) { @@ -574,7 +594,6 @@ Danbooru.Note = { $note_body.html("Click to edit"); $("#note-container").append($note_box); $("#note-container").append($note_body); - Danbooru.Note.Body.resize($note_body); Danbooru.Note.Box.resize_inner_border($note_box); Danbooru.Note.id += "x"; }, @@ -588,9 +607,11 @@ Danbooru.Note = { }, load_all: function() { + var fragment = document.createDocumentFragment(); $.each($("#notes article"), function(i, article) { var $article = $(article); Danbooru.Note.add( + fragment, $article.data("id"), $article.data("x"), $article.data("y"), @@ -599,12 +620,7 @@ Danbooru.Note = { $article.html() ); }); - - $('#note-container').css('display','none'); - $('.note-box').each(function(i, v) { - $(v).css('display','block') - }); - $('#note-container').css('display','block'); + $("#note-container").append(fragment); } } diff --git a/app/assets/javascripts/posts.js b/app/assets/javascripts/posts.js index bc8fc85c1..1b54c627d 100644 --- a/app/assets/javascripts/posts.js +++ b/app/assets/javascripts/posts.js @@ -4,7 +4,7 @@ Danbooru.Post.pending_update_count = 0; Danbooru.Post.initialize_all = function() { - this.initialize_titles(); + this.initialize_post_previews(); if ($("#c-posts").length) { if (Danbooru.meta("enable-js-navigation") === "true") { @@ -182,9 +182,10 @@ }); } - Danbooru.Post.initialize_titles = function() { + Danbooru.Post.initialize_post_previews = function() { $(".post-preview").each(function(i, v) { Danbooru.Post.initialize_title_for(v); + Danbooru.Post.initialize_preview_borders_for(v); }); } @@ -194,6 +195,36 @@ $img.attr("title", $post.attr("data-tags") + " user:" + $post.attr("data-uploader") + " rating:" + $post.data("rating") + " score:" + $post.data("score")); } + Danbooru.Post.initialize_preview_borders_for = function(post) { + var $post = $(post); + var $img = $post.find("img"); + + var border_colors = []; + + if ($post.hasClass("post-status-has-children")) { + border_colors.push("#0F0"); + } + if ($post.hasClass("post-status-has-parent")) { + border_colors.push("#CC0"); + } + if ($post.hasClass("post-status-deleted")) { + border_colors.push("#000"); + } else if ($post.hasClass("post-status-pending")) { + border_colors.push("#00F"); + } else if ($post.hasClass("post-status-flagged")) { + border_colors.push("#F00"); + } + + if (border_colors.length > 1) { + $img.css("border", "2px solid"); + if (border_colors.length === 3) { + $img.css("border-color", border_colors[0] + " " + border_colors[2] + " " + border_colors[2] + " " + border_colors[1]); + } else if (border_colors.length === 2) { + $img.css("border-color", border_colors[0] + " " + border_colors[1] + " " + border_colors[1] + " " + border_colors[0]); + } + } + } + Danbooru.Post.initialize_post_image_resize_links = function() { $("#image-resize-link").click(function(e) { var $link = $(e.target); diff --git a/app/assets/javascripts/related_tag.js b/app/assets/javascripts/related_tag.js index 39cd2d7de..b4586cc34 100644 --- a/app/assets/javascripts/related_tag.js +++ b/app/assets/javascripts/related_tag.js @@ -164,7 +164,7 @@ var $ul = $("
This tag has been aliased to " + html << link_to(antecedent_alias.consequent_name, show_or_new_wiki_pages_path(:title => antecedent_alias.consequent_name)) + html << ".
" + end + + if consequent_aliases.any? + html << "The following tags are aliased to this tag: " + html << raw(consequent_aliases.map {|x| link_to(x.antecedent_name, show_or_new_wiki_pages_path(:title => x.antecedent_name))}.join(", ")) + html << ".
" + end + + if antecedent_implications.any? + html << "This tag implicates " + html << raw(antecedent_implications.map {|x| link_to(x.consequent_name, show_or_new_wiki_pages_path(:title => x.consequent_name))}.join(", ")) + html << ".
" + end + + if consequent_implications.any? + html << "The following tags implicate this tag: " + html << raw(consequent_implications.map {|x| link_to(x.antecedent_name, show_or_new_wiki_pages_path(:title => x.antecedent_name))}.join(", ")) + html << ".
" + end + + html.html_safe + end end diff --git a/app/models/news_update.rb b/app/models/news_update.rb index 5fa37bbc0..29755564b 100644 --- a/app/models/news_update.rb +++ b/app/models/news_update.rb @@ -1,6 +1,6 @@ class NewsUpdate < ActiveRecord::Base belongs_to :creator, :class_name => "User" - belongs_to :udpater, :class_name => "User" + belongs_to :updater, :class_name => "User" scope :recent, order("created_at desc").limit(5) before_validation :initialize_creator, :on => :create before_validation :initialize_updater diff --git a/app/models/post_flag.rb b/app/models/post_flag.rb index e125d0bb2..800d8c988 100644 --- a/app/models/post_flag.rb +++ b/app/models/post_flag.rb @@ -68,9 +68,6 @@ class PostFlag < ActiveRecord::Base if post.is_deleted? errors[:post] << "is deleted" false - elsif post.is_pending? - errors[:post] << "is pending" - false else true end diff --git a/app/models/tag_subscription.rb b/app/models/tag_subscription.rb index cc049ca56..d745ff9aa 100644 --- a/app/models/tag_subscription.rb +++ b/app/models/tag_subscription.rb @@ -6,7 +6,7 @@ class TagSubscription < ActiveRecord::Base before_save :limit_tag_count attr_accessible :name, :tag_query, :post_ids, :is_public, :is_visible_on_profile validates_presence_of :name, :tag_query, :creator_id - validates_format_of :tag_query, :with => /^(?:\S+\s*){1,20}$/m, :message => "can have up to 20 tags" + validates_format_of :tag_query, :with => /\A(?:\S*\s*){1,20}\Z/, :message => "can have up to 20 tags" validate :creator_can_create_subscriptions, :on => :create def normalize_name diff --git a/app/models/user.rb b/app/models/user.rb index d84a31b07..bf9d87e89 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -510,13 +510,15 @@ class User < ActiveRecord::Base module ApiMethods def hidden_attributes - super + [:password_hash, :bcrypt_password_hash, :email, :email_verification_key, :time_zone, :created_at, :updated_at, :receive_email_notifications, :last_logged_in_at, :last_forum_read_at, :has_mail, :default_image_size, :comment_threshold, :always_resize_images, :favorite_tags, :blacklisted_tags, :base_upload_limit, :recent_tags, :enable_privacy_mode, :enable_post_navigation, :new_post_navigation_layout, :enable_sequential_post_navigation, :hide_deleted_posts, :per_page, :style_usernames] + super + [:password_hash, :bcrypt_password_hash, :email, :email_verification_key, :time_zone, :updated_at, :receive_email_notifications, :last_logged_in_at, :last_forum_read_at, :has_mail, :default_image_size, :comment_threshold, :always_resize_images, :favorite_tags, :blacklisted_tags, :recent_tags, :enable_privacy_mode, :enable_post_navigation, :new_post_navigation_layout, :enable_sequential_post_navigation, :hide_deleted_posts, :per_page, :style_usernames] end def serializable_hash(options = {}) options ||= {} options[:except] ||= [] options[:except] += hidden_attributes + options[:methods] ||= [] + options[:methods] += [:wiki_page_version_count, :artist_version_count, :pool_version_count, :forum_post_count, :comment_count] super(options) end @@ -525,6 +527,8 @@ class User < ActiveRecord::Base options ||= {} options[:except] ||= [] options[:except] += hidden_attributes + options[:methods] ||= [] + options[:methods] += [:wiki_page_version_count, :artist_version_count, :pool_version_count, :forum_post_count, :comment_count] super(options, &block) end @@ -538,6 +542,28 @@ class User < ActiveRecord::Base end end + module CountMethods + def wiki_page_version_count + WikiPageVersion.for_user(id).count + end + + def artist_version_count + ArtistVersion.for_user(id).count + end + + def pool_version_count + PoolVersion.for_user(id).count + end + + def forum_post_count + ForumPost.for_user(id).count + end + + def comment_count + Comment.for_creator(id).count + end + end + module SearchMethods def named(name) where("lower(name) = ?", name) @@ -628,6 +654,7 @@ class User < ActiveRecord::Base include LimitMethods include InvitationMethods include ApiMethods + include CountMethods extend SearchMethods def initialize_default_image_size diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb index 5c2a704c3..d3678c13d 100644 --- a/app/presenters/post_presenter.rb +++ b/app/presenters/post_presenter.rb @@ -181,7 +181,7 @@ class PostPresenter < Presenter end def pool_link_html(template, pool, options = {}) - pool_html = ['