Bug: if you moused over another note while dragging a note, it would
trigger a note body popup. This would also happen when drawing out a new
note.
Also fix the drag box for new notes being drawn behind other notes.
Bug: loading and saving a note without moving it could change the note's
position. Moving a note with the keyboard could also cause unintended
changes to the note's size or position. This was because of floating
point errors when converting from percentage coordinates (floats) to pixel
coordinates (integers).
Fix: store note coordinates as pixel coordinates instead of as
percentage coordinates. Percentages are only used to position notes for
display.
Also fix it so you can resize rotated notes with the keyboard. This was
disabled before.
* Raise notes when hovering over them. This is so that when dragging
embedded notes, they're not hidden behind other notes. Also so that if
two notes are overlapping, you can hover over one to raise it over the
other.
* Replace .hovering class with :hover selector.
Bug: if you used they keyboard to move or resize a note, then the note
body would stay visible, which could get in the way when moving in the
down direction.
Bug: if you're editing a note and click preview, then you resize the
image or press V to toggle the image size, then the note body will stay
on the screen in the wrong position.
Bug: previewing a note would mark the note as unsaved even if the note
hadn't been changed.
Fix: mark the note as unsaved when the user types something into the
note edit box, not when the note is previewed.
Rewrite the notes Javascript from a procedural style to an
object-oriented style.
Before the notes Javascript had a lot of problems:
* There was hidden state everywhere, both locally and globally. We had
state in global variables, in <meta> tags, in DOM data-* attributes
(on multiple elements), and in jQuery .data() properties (which are
different from data-* attributes, because they aren't visible in the
DOM).
* Local state was hard to reason about. There was lots of direct DOM
manipulation in random places. Functions had to constantly pass around
note ids and look up elements in the DOM to get the state. State was
invisible because it was stored as jQuery .data() properties. It was
hard to follow where state was stored, how it was initialized, and how
it changed.
* Global state was also a mess. There were a lot of global flags and
variables only used in specific situations. Almost all of this state was
unnecessary. Global state also prevented us from doing things like
loading or unloading posts dynamically, or showing multiple posts with
notes on the same page.
* There was a lot of duplication of code, especially for placing notes,
and for loading or saving new notes versus saved notes.
Now the code is organized in an object-oriented fashion:
* The Note class represents a single note. A post has a list of notes,
and each note object has a Note.Box and a Note.Body. Together these
objects encapsulate the note's state.
* Notes have methods for doing things like placing note boxes, or showing
and hiding note bodies, or creating, saving, or deleting notes. This
makes the JS API cleaner.
* Global state is kept to a minimum.
This is one big patch because it was too hard to make these changes
incrementally. There are a couple minor bugfixes, but the actual
behavior of notes should remain unchanged.
Bugfixes:
* It was possible to enter translation mode, start dragging a new note,
then press N to leave translation mode while still dragging the note.
If you did this, then you would be stuck in translation mode and you
couldn't stop dragging the note.
* Placement of new notes is now pixel-perfect. Before when placing a
note, the note would shift by 1-2 pixels.
* Previewing an empty note didn't show the "Click to edit" message.
Other noteworthy changes:
* Most global state has been eliminated. There were a lot of flags and
variables stored as global variables on `Danbooru.Note`. Most of these
turned out to be either unnecessary or even unused.
* Notes now have an explicit minimum size of 10x10 pixels. Before this
limit was hardcoded and undocumented.
* A lot of the note placement and note creation code has been simplified.
* `Note.add()` and `Note.create()` have been refactored into `new Note()`.
Before `Note.add` was used to load an existing note, while `Note.create`
was used to create a new note. These did the same thing, but had
slightly different behavior.
* `Note.Box.scale()` and `Note.box.update_data_attributes` have been
refactored into `Note.Box.place_note()`. Contrary to their names,
these functions were actually both used to place notes.
Notes are not given percent coordinates when created, however moving
or resizing would update the coordinates to percentage. This is why
it was appearing as if the type of coordinates given were random.
The issue is that the body of the embedded notes were being set to
the value which tells the script not to read the original body after
saving a note. This was a poor system prone to issues, so instead a
DOM class is now explicitly added to the notes on note creation and
cleared whenever a note gets saved.
Additionally, the embedded note bodies were standardized to use the
same initial value as non-embedded notes as well.
This was also causing the movable status on new notes to require
clicking twice to remove that status since the note ID gets changed
but the move ID wasn't.
If the image is blacklisted on initial page load then unblacklisted
after the image is loaded, then the notes will be mispositioned at the
bottom of the image. This is because we relied on $image.height() to
calculate the note position, but the image height is zero when the image
is hidden.
Potential fix for #4370.
* Add back "Resize to window" link.
* Add Z shortcut for resize to window link (mnemonic: Z for zoom image).
* Resize images to screen width by default on both desktop and mobile.
* Make it so that notes are nested directly inside the .image-container
element with the image, instead of inside a separate .note-container
element. This means .image-container and .note-container are now the
same element. This is so that the size of the .note-container is
driven by the size of the image, which ensures that notes are
automatically resized as the image is resized.
Change #image-container and #note-container from IDs to classes. This is
necessary so that we can use one container element for both the image
container and the note container. This may break custom CSS and
userscripts.
- This is because the note body of one note box could hide another note box
- The only option to hide the note body previously was to double tap the image
- This allows for the note boxes to be easily resized
-- Now resizing the note container resizes all of the note boxes
-- The z-index and position values had to be adjusted for this
--- So that the note/preview boxes were still visible
--- So that the image was selectable with right clicks
- All of the inner box styles have been moved to the outer box
-- Now the inner box is only a container for the note body
- The always resize image option has been removed from user settings
-- The value still exists on the model for future rename/reuse
- The max width is set at 100% for responsive mode to fit the screen
Beforehand it was always using the left corner, which was causing
the note body to be to the right of the note box whenever the bottom
angle of the note box was descending. Now it selects the left or
the right corner depending on the angle, which keeps the note body
in a better position right beneath the note box.
- Attributes are pulled from the first element with class "note-box-attributes"
- Transform is note box only to prevent applying the same transform twice
-- Only rotations are allowed to prevent excessive scaling of note boxes
-- Note box positions are adjusted after drag/nudge/resize to prevent out-of-bounds
-- The note body is placed on the lowest box corner that is farthest left
- Background color is inner box only since the note box is already transparent
-- Backgrounds with any transparency aren't allowed as they would interfere with the text below
- Border radius is both since they both have borders
- Add full namespaces to all event removes to prevent bad removes
- Notes must be clicked in order to engage the nudge function for that note
-- This status is indicated by a green border around the note
-- Clicking the note or another note will turn off nudging for that note
- Also prevent notes from being nudged outside of the image borders
- Each element has the size style elements scaled to the font size with "em"
-- The font size of the element is scaled in percentage to the parent element
- All sizes are then scaled by changing the font size of the note container
- The scale resize calculation uses the large image size
-- Since this is the assumed default size for a user
- Preview sets the font size of the inner box to the base font size
-- This allows the calculations to be performed correctly
- Use CSS classes instead of applying the styles to the elements.
-- Allows a user to override any of the default styles being applied.
- Remove the borders and handles when not hovering over the box.
- Increase the opacity for embedded notes to full to avoid conflicts with
the text underneath.
- Decrease the opacity a little when editing embedded notes.
-- Allows for better seeing of the text underneath while still being able
to see the translation text above.
-- Compensated for by showing full opacity when hovering over the note box.
Refactor things to store information about the current user as data
attributes on the <body> tag rather than as <meta> tags. These <meta>
tags are now deprecated and will be eventually removed.
* Store all of the current user's API attributes as data attributes on
the <body> tag.
* Add `CurrentUser.data` for getting data from the <body> tag, and
use it instead of `Utility.meta`.
* Add `CurrentUser.update` for updating the current user's settings.
* Fix a bug with the user named "Anonymous" not being able to edit notes.