744 lines
38 KiB
HTML
744 lines
38 KiB
HTML
{{define "title"}}Upload a Photo{{end}}
|
|
{{define "content"}}
|
|
<div class="container">
|
|
<section class="hero is-link is-bold">
|
|
<div class="hero-body">
|
|
<div class="container">
|
|
<h1 class="title">
|
|
{{if .EditPhoto}}
|
|
Edit Photo
|
|
{{else if eq .Intent "profile_pic"}}
|
|
Upload a Profile Picture
|
|
{{else}}
|
|
Upload a Photo
|
|
{{end}}
|
|
</h1>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{{ $Root := . }}
|
|
{{ $User := .CurrentUser }}
|
|
|
|
<!-- Drag/Drop Modal -->
|
|
<div class="modal" id="drop-modal">
|
|
<div class="modal-background"></div>
|
|
<div class="modal-content">
|
|
<div class="box content has-text-centered">
|
|
<h1><i class="fa fa-upload mr-2"></i> Drop image to select it for upload</h1>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{if .EditPhoto}}
|
|
<form action="/photo/edit" method="POST">
|
|
<input type="hidden" name="id" value="{{.EditPhoto.ID}}">
|
|
{{else}}
|
|
<form action="/photo/upload" method="POST" enctype="multipart/form-data">
|
|
{{end}}
|
|
{{InputCSRF}}
|
|
<input type="hidden" id="intent" name="intent" value="{{.Intent}}">
|
|
|
|
<div class="block p-4">
|
|
<!-- Upload disclaimers, but not if editing a photo -->
|
|
{{if not .EditPhoto}}
|
|
<div class="content block">
|
|
<p>
|
|
You can use this page to upload a new photo to your profile. Please remember
|
|
the rules below:
|
|
</p>
|
|
|
|
<ul>
|
|
<li>
|
|
🤳 <strong>Self pictures only:</strong> you may only upload pictures which depict
|
|
<em>you</em> in them. If the picture also contains other people, be sure you
|
|
have their consent to post it here!
|
|
</li>
|
|
<li>
|
|
🔞 <strong>Mark whether your picture is explicit:</strong> not all nudists want to
|
|
see sexual content or close-up shots of genitalia. If your picture is not a
|
|
"normal nude" please check the Explicit box to help the rest of us out!
|
|
</li>
|
|
<li>
|
|
🧑 <strong>Your main profile picture must show your face:</strong> it doesn't have
|
|
to be a nude pic but your face needs to be in it. Additional photos uploaded to
|
|
your page do not need to require your face in them.
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- Quota notification -->
|
|
{{if not .EditPhoto}}
|
|
<div class="notification {{if ge .PhotoCount .PhotoQuota}}is-warning{{else}}is-info{{end}} block">
|
|
<p class="block">
|
|
You have currently uploaded <strong>{{.PhotoCount}}</strong> of your allowed {{.PhotoQuota}} photos.
|
|
{{if ge .PhotoCount .PhotoQuota}}
|
|
To upload a new photo, please <a href="/u/{{.CurrentUser.Username}}/photos">delete</a>
|
|
an existing photo first to make room.
|
|
{{end}}
|
|
</p>
|
|
|
|
{{if and (eq .Intent "profile_pic") (ge .PhotoCount .PhotoQuota)}}
|
|
<p class="block">
|
|
You have reached your maximum number of photos. <strong>To use one of your existing photos as your profile picture,</strong>
|
|
please visit your <a href="/u/{{.CurrentUser.Username}}/photos">Gallery page</a>, click on the "Edit" button for a photo,
|
|
then the button to set it as your profile picture will appear on the Edit page. Remember to click "Save" when done!
|
|
</p>
|
|
{{else}}
|
|
<p class="block">
|
|
You may upload <strong>{{SubtractInt .PhotoQuota .PhotoCount}}</strong> more photo{{Pluralize (SubtractInt .PhotoQuota .PhotoCount)}}.
|
|
{{if not .CurrentUser.Certified}}
|
|
After your account has been <a href="/photo/certification">certified</a>, you will be able to upload
|
|
additional pictures.
|
|
{{end}}
|
|
</p>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- No profile picture and they aren't uploading one now? -->
|
|
{{if .NoProfilePicture}}
|
|
<div class="notification is-warning block">
|
|
<p class="block">
|
|
<strong>Notice:</strong> you currently do not have a Default Profile Picture set up on your
|
|
account. You can <a href="/photo/upload?intent=profile_pic">click here to upload a new one</a>
|
|
or click the Edit button on <a href="/u/{{.CurrentUser.Username}}/photos">one of your existing photos</a>
|
|
to crop a square profile picture from one of them.
|
|
</p>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if or .EditPhoto (lt .PhotoCount .PhotoQuota)}}
|
|
<div class="columns">
|
|
<div class="column">
|
|
|
|
<div class="card">
|
|
<header class="card-header has-background-link">
|
|
<p class="card-header-title has-text-light">
|
|
<i class="fa fa-camera pr-2"></i>
|
|
{{if .EditPhoto}}
|
|
Your Photo
|
|
{{else}}
|
|
Select a Photo
|
|
{{end}}
|
|
</p>
|
|
</header>
|
|
|
|
<!-- Upload field, not when editing -->
|
|
{{if not .EditPhoto}}
|
|
<div class="card-content">
|
|
<p class="block">
|
|
Browse or drag a photo onto this page:
|
|
</p>
|
|
|
|
<div class="field block">
|
|
<div class="file has-name is-fullwidth">
|
|
<label class="file-label">
|
|
<input class="file-input" type="file"
|
|
name="file"
|
|
id="file"
|
|
accept=".jpg,.jpeg,.jpe,.png{{if ne .Intent "profile_pic"}},.gif{{end}}"
|
|
required>
|
|
<span class="file-cta">
|
|
<span class="file-icon">
|
|
<i class="fas fa-upload"></i>
|
|
</span>
|
|
<span class="file-label">
|
|
Choose a file…
|
|
</span>
|
|
</span>
|
|
<span class="file-name" id="fileName">
|
|
Select a file
|
|
</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="box" id="imagePreview" style="display: none">
|
|
<h3 class="subtitle">
|
|
{{if .NeedsCrop}}Crop image:{{else}}Selected image:{{end}}
|
|
</h3>
|
|
|
|
{{if .NeedsCrop}}
|
|
<p class="block">
|
|
Select a square crop of this image for your profile picture. The full
|
|
image will go among the rest of your photos, and the square version
|
|
will be used as your profile pic and avatar.
|
|
</p>
|
|
{{end}}
|
|
|
|
<!-- Container of img tags for the selected photo preview. -->
|
|
<div id="previewBox" class="block"></div>
|
|
|
|
{{if .NeedsCrop}}
|
|
<div class="block has-text-centered">
|
|
<button type="button" class="button block is-info" onclick="resetCrop()">Reset</button>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
<!-- Holder of image crop coordinates in x,y,w,h format. -->
|
|
<input type="hidden" name="crop" id="cropCoords">
|
|
</div>
|
|
{{else}}<!-- when .EditPhoto -->
|
|
<div class="card-content">
|
|
<figure id="editphoto-preview" class="image block">
|
|
{{if HasSuffix .EditPhoto.Filename ".mp4"}}
|
|
<video autoplay loop controls controlsList="nodownload" playsinline>
|
|
<source src="{{PhotoURL .EditPhoto.Filename}}" type="video/mp4">
|
|
</video>
|
|
{{else}}
|
|
<img src="{{PhotoURL .EditPhoto.Filename}}" id="editphoto-img">
|
|
{{end}}
|
|
</figure>
|
|
|
|
<!-- Re-crop as profile picture: not when it's a GIF -->
|
|
{{if not (HasSuffix .EditPhoto.Filename ".mp4")}}
|
|
<div class="block has-text-centered" id="editphoto-begin-crop">
|
|
<button type="button" class="button" onclick="setProfilePhoto()">
|
|
<span class="icon"><i class="fa fa-crop-simple"></i></span>
|
|
<span>Set this as my profile photo (crop image)</span>
|
|
</button>
|
|
</div>
|
|
{{end}}
|
|
|
|
<div class="block has-text-centered" id="editphoto-cropping" style="display: none">
|
|
<button type="button" class="button block is-info" onclick="resetCrop()">Reset</button>
|
|
</div>
|
|
|
|
<!-- Holder of image crop coordinates in x,y,w,h format. -->
|
|
<input type="hidden" name="crop" id="cropCoords">
|
|
</div>
|
|
{{end}}
|
|
|
|
</div><!-- /card -->
|
|
</div><!-- /column -->
|
|
|
|
<div class="column">
|
|
|
|
<div class="card">
|
|
<header class="card-header has-background-link">
|
|
<p class="card-header-title has-text-light">
|
|
<i class="fa fa-pencil pr-2"></i>
|
|
Photo Settings
|
|
</p>
|
|
</header>
|
|
|
|
<div class="card-content">
|
|
|
|
<div class="field mb-5">
|
|
<label class="label" for="caption">Caption</label>
|
|
<input type="text" class="input"
|
|
name="caption"
|
|
id="caption"
|
|
placeholder="A short sentence about this picture"
|
|
value="{{.EditPhoto.Caption}}">
|
|
</div>
|
|
|
|
<div class="field mb-5">
|
|
<div class="columns is-mobile mb-0">
|
|
<div class="column">
|
|
<label class="label" for="alt_text">Alt Text</label>
|
|
</div>
|
|
<div class="column is-narrow">
|
|
<small id="alt_text_length">0/5000</small>
|
|
</div>
|
|
</div>
|
|
|
|
<textarea class="textarea"
|
|
name="alt_text"
|
|
id="alt_text"
|
|
cols="40"
|
|
rows="4"
|
|
placeholder="Write a description of this photo for the visually impaired"
|
|
>{{.EditPhoto.AltText}}</textarea>
|
|
<p class="help">
|
|
Write a description of this photo to help people with disabilities (such as the
|
|
vision impaired) to understand the content and meaning of this photo.
|
|
Max 5,000 characters.
|
|
<a href="/faq#alt-text" target="_blank">Learn more <i class="fa fa-external-link"></i></a>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="field mb-5">
|
|
<label class="label">
|
|
<i class="fa fa-thumbtack mr-1 has-text-success"></i>
|
|
Pinned Photo
|
|
</label>
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="pinned"
|
|
value="true"
|
|
{{if .EditPhoto.Pinned}}checked{{end}}>
|
|
Keep this photo at the top of my gallery
|
|
</label>
|
|
<p class="help">
|
|
You may "pin" your favorite photos to keep them always at the front of
|
|
your photo gallery.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="field mb-5">
|
|
<label class="label">Photo Visibility</label>
|
|
<div>
|
|
<label class="radio">
|
|
<input type="radio"
|
|
name="visibility"
|
|
value="public"
|
|
{{if or (not .EditPhoto) (eq .EditPhoto.Visibility "public")}}checked{{end}}>
|
|
<strong class="has-text-link ml-1">
|
|
<span>Public <small>(members only)</small></span>
|
|
<span class="icon"><i class="fa fa-eye"></i></span>
|
|
</strong>
|
|
</label>
|
|
<p class="help">
|
|
This photo will appear on your profile page and can be seen by any
|
|
logged-in user account. It may also appear on the site-wide Photo
|
|
Gallery if that option is enabled, below.
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<label class="radio">
|
|
<input type="radio"
|
|
name="visibility"
|
|
value="friends"
|
|
{{if eq .EditPhoto.Visibility "friends"}}checked{{end}}>
|
|
<strong class="has-text-warning ml-1">
|
|
<span>Friends only</span>
|
|
<span class="icon"><i class="fa fa-user-group"></i></span>
|
|
</strong>
|
|
</label>
|
|
<p class="help">
|
|
Only users you have accepted as a friend can see this photo on your
|
|
profile page and on the site-wide Photo Gallery if that option is
|
|
enabled, below.
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<label class="radio">
|
|
<input type="radio"
|
|
name="visibility"
|
|
value="private"
|
|
{{if eq .EditPhoto.Visibility "private"}}checked{{end}}>
|
|
<strong class="has-text-private ml-1">
|
|
<span>Private</span>
|
|
<span class="icon"><i class="fa fa-lock"></i></span>
|
|
</strong>
|
|
</label>
|
|
<p class="help">
|
|
This photo is visible only to you and to users for whom you have
|
|
granted access
|
|
(<a href="/photo/private" target="_blank" class="has-text-private">manage grants <i class="fa fa-external-link"></i></a>).
|
|
</p>
|
|
</div>
|
|
|
|
<div class="has-text-warning is-size-7 mt-4">
|
|
<i class="fa fa-info-circle mr-1"></i>
|
|
<strong class="has-text-warning">Reminder:</strong> There are risks inherent with sharing
|
|
pictures on the Internet, and {{PrettyTitle}} can't guarantee that another member of the site
|
|
won't download and possibly redistribute your photos. You may mark your picture as "Friends only"
|
|
or "Private" to limit who on the website will see it, but anybody who <em>can</em> see it could potentially
|
|
save it to their computer. <a href="/faq#downloading" target="_blank">Learn more <i class="fa fa-external-link"></i></a>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="field mb-5">
|
|
<label class="label">
|
|
<span>Site Photo Gallery</span>
|
|
<span class="icon"><i class="fa fa-image"></i></span>
|
|
</label>
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="gallery"
|
|
value="true"
|
|
{{if and (or .EditPhoto.Gallery (not .EditPhoto)) (not .SiteGalleryThrottled)}}checked{{end}}
|
|
{{if .SiteGalleryThrottled}}disabled{{end}}>
|
|
{{if .SiteGalleryThrottled}}<del>{{end}}
|
|
Show this photo in the site-wide Photo Gallery
|
|
{{if .SiteGalleryThrottled}}</del>{{end}}
|
|
</label>
|
|
|
|
{{if .SiteGalleryThrottled}}
|
|
<p class="help has-text-warning">
|
|
<i class="fa fa-exclamation-triangle"></i>
|
|
You have shared too many photos with the Site Gallery recently!<br><br>
|
|
We currently limit members to featuring <strong>{{.SiteGalleryThrottleLimit}} photos</strong>
|
|
on the Site Gallery per day, so that one member doesn't dominate page after
|
|
page of the gallery by uploading <em>all</em> of their pictures at once.
|
|
<a href="/faq#site-gallery-throttle" target="_blank">Learn more <i class="fa fa-external-link"></i></a>
|
|
<br><br>
|
|
You may still upload all the photos you like to <em>your</em> gallery, but new ones can not be featured
|
|
on the Site Gallery until you have waited 24 hours. You MAY "edit" your recently posted photos
|
|
and un-check the Site Gallery box if you <em>really</em> want this one to be featured now.
|
|
</p>
|
|
{{else}}
|
|
<p class="help">
|
|
Leave this box checked and your photo can appear in the site's Photo Gallery
|
|
page. Mainly your <strong class="has-text-link">Public</strong> photos will appear
|
|
on the Gallery, and your approved friends may see your
|
|
<strong class="has-text-warning">Friends-only</strong> photos there as well.
|
|
<strong class="has-text-private">Private</strong> photos may appear in
|
|
the gallery to users whom you have granted access. If this is undesirable,
|
|
un-check the Gallery box to skip the Site Gallery.
|
|
</p>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div class="field mb-5">
|
|
<label class="label has-text-danger">
|
|
<span>Explicit Content</span>
|
|
<span class="icon"><i class="fa fa-fire"></i></span>
|
|
</label>
|
|
|
|
<!-- Flagged Explicit photo: show a warning if this photo was recently flagged by the community. -->
|
|
{{$IsFlagged := and .EditPhoto .EditPhoto.Flagged .EditPhoto.Explicit}}
|
|
{{if $IsFlagged}}
|
|
<div class="notification is-danger is-light py-3 px-3 has-text-smaller content">
|
|
<p>
|
|
<strong>
|
|
<i class="fa fa-exclamation-triangle"></i>
|
|
Notice:
|
|
</strong>
|
|
This photo was classified by the community as containing 'Explicit' content.
|
|
</p>
|
|
|
|
<p>
|
|
Please review <a href="/tos/photos#explicit" target="_blank">what {{.Title}} considers an 'Explicit' photo</a>
|
|
and if this photo fits the description, <strong>please</strong> leave this photo with the
|
|
'Explicit' box checked, below.
|
|
</p>
|
|
|
|
<p>
|
|
If you disagree that this photo should have been marked as 'Explicit,' you <strong>MAY</strong>
|
|
uncheck the box below and remove the Explicit status. <strong>Note:</strong> the website admin will
|
|
be notified to take a look as well if you do this, to verify that your photo has the correct 'Explicit'
|
|
setting.
|
|
</p>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if eq .Intent "profile_pic"}}
|
|
<span class="has-text-danger">
|
|
Your default profile picture should
|
|
<strong class="has-text-danger">NOT</strong>
|
|
contain explicit content.
|
|
</span>
|
|
|
|
<p class="help">
|
|
Your default profile picture is about your face. You can have nudity
|
|
in it, too, but not a close-up shot of your genitals or sporting an
|
|
erection or engaging in sexual conduct. You can upload pictures like
|
|
that to your page, just not as your default profile picture!
|
|
</p>
|
|
{{else}}
|
|
<label class="checkbox"
|
|
{{if $IsFlagged}}title="You MAY remove this check if you disagree that this photo should be marked Explicit"{{end}}
|
|
>
|
|
<input type="checkbox"
|
|
name="explicit"
|
|
value="true"
|
|
{{if .EditPhoto.Explicit}}checked{{end}}
|
|
{{if .EditPhoto.HasAdminLabelForceExplicit}}disabled{{end}}>
|
|
{{if $IsFlagged}}<del class="cursor-not-allowed">{{end}}
|
|
This photo contains explicit content
|
|
{{if $IsFlagged}}</del>{{end}}
|
|
</label>
|
|
<p class="help">
|
|
Mark this box if this photo contains any explicit content, including an
|
|
erect penis, close-up of genitalia, or any depiction of sexual activity.
|
|
Use your best judgment.<br><br>
|
|
Please see
|
|
<a href="/tos/photos#explicit" target="_blank">what {{PrettyTitle}} considers to be an Explicit photo <i class="fa fa-external-link"></i></a>
|
|
on our <a href="/tos/photos" target="_blank">Photo Policy</a> page.
|
|
</p>
|
|
{{end}}
|
|
</div>
|
|
|
|
{{if not .EditPhoto}}
|
|
<div class="field">
|
|
<label class="label">Confirm Upload</label>
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="confirm1"
|
|
value="true"
|
|
required>
|
|
I assert that this is a photo <strong>of myself</strong> and that I have
|
|
permission to upload this picture.
|
|
</label>
|
|
|
|
{{if eq .Intent "profile_pic"}}
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="confirm2"
|
|
value="true"
|
|
required>
|
|
I assert that this picture shows my face and is not explicit
|
|
</label>
|
|
{{else}}
|
|
<input type="hidden" name="confirm2" value="true">
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
|
|
<div class="field">
|
|
<button type="submit" class="button is-primary">
|
|
{{if .EditPhoto}}
|
|
Save Changes
|
|
{{else}}
|
|
Upload Photo
|
|
{{end}}
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Admin Labels -->
|
|
{{if and .EditPhoto (.RequestUser.HasAdminScope "social.moderator.photo")}}
|
|
<hr>
|
|
<div class="field">
|
|
<label class="label has-text-danger">
|
|
<span>Admin Labels</span>
|
|
<span class="icon"><i class="fa fa-peace"></i></span>
|
|
</label>
|
|
|
|
<p class="help">
|
|
The options below can apply moderation rules to this picture, especially regarding
|
|
its 'explicit' status. For example: if a community member flagged this picture as
|
|
explicit, but it does NOT need to be marked as such, select that label below: and
|
|
the website will no longer allow this photo to be flagged as explicit again.
|
|
</p>
|
|
</div>
|
|
|
|
{{range .AvailableAdminLabels}}
|
|
<div class="field">
|
|
<label class="checkbox">
|
|
<input type="checkbox"
|
|
name="admin_label"
|
|
value="{{.Value}}"
|
|
{{if ($Root.EditPhoto.HasAdminLabel .Value)}}checked{{end}}>
|
|
{{.Label}}
|
|
</label>
|
|
<p class="help">
|
|
{{.Help}}
|
|
</p>
|
|
</div>
|
|
{{end}}
|
|
|
|
<p class="help">
|
|
<strong>Reminder:</strong> click on 'Save Changes' to apply these labels!
|
|
</p>
|
|
|
|
{{end}}
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div><!-- /columns -->
|
|
{{end}}<!-- if under quota -->
|
|
</div>
|
|
</form>
|
|
|
|
<!-- image cropper -->
|
|
<link rel="stylesheet" href="/static/js/croppr/croppr.min.css">
|
|
<script src="/static/js/croppr/croppr.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
var croppr = null;
|
|
const usingCroppr = {{if .NeedsCrop}}true{{else}}false{{end}};
|
|
|
|
function resetCrop() {
|
|
if (croppr !== null) {
|
|
croppr.reset();
|
|
}
|
|
}
|
|
|
|
{{if not .EditPhoto}}
|
|
window.addEventListener("DOMContentLoaded", (event) => {
|
|
let $file = document.querySelector("#file"),
|
|
$fileName = document.querySelector("#fileName"),
|
|
$hiddenPreview = document.querySelector("#imagePreview"),
|
|
$previewBox = document.querySelector("#previewBox"),
|
|
$cropField = document.querySelector("#cropCoords"),
|
|
$dropArea = document.querySelector("#drop-modal"),
|
|
$body = document.querySelector("body");
|
|
|
|
// Common handler for file selection, either via input
|
|
// field or drag/drop onto the page.
|
|
let onFile = (file) => {
|
|
// Too large? (8 MB GIFs) - NOTE: also see config.go so this matches.
|
|
if (file.size >= 1024*1024*8) {
|
|
window.alert("That file is too large! Choose something less than 8 MB.");
|
|
return;
|
|
}
|
|
|
|
$fileName.innerHTML = file.name;
|
|
|
|
// Read the image to show the preview on-page.
|
|
const reader = new FileReader();
|
|
reader.addEventListener("load", () => {
|
|
const uploadedImg = reader.result;
|
|
$hiddenPreview.style.display = "block";
|
|
|
|
// Create a new <img> tag the first time.
|
|
if (croppr !== null) {
|
|
croppr.setImage(uploadedImg);
|
|
croppr.reset();
|
|
return;
|
|
}
|
|
|
|
// If not using croppr, flush the old img preview out.
|
|
if (!usingCroppr) {
|
|
$previewBox.innerHTML = "";
|
|
}
|
|
|
|
let img = document.createElement("img");
|
|
img.src = uploadedImg;
|
|
img.style.display = "block";
|
|
img.style.maxWidth = "100%";
|
|
img.style.height = "auto";
|
|
|
|
// Add it to the wrapper div.
|
|
$previewBox.appendChild(img);
|
|
|
|
if (usingCroppr) {
|
|
croppr = new Croppr(img, {
|
|
aspectRatio: 1,
|
|
minSize: [ 32, 32, 'px' ],
|
|
returnMode: 'real',
|
|
onCropStart: (data) => {
|
|
// console.log(data);
|
|
},
|
|
onCropMove: (data) => {
|
|
// console.log(data);
|
|
},
|
|
onCropEnd: (data) => {
|
|
// console.log(data);
|
|
$cropField.value = [
|
|
data.x, data.y, data.width, data.height
|
|
].join(",");
|
|
},
|
|
onInitialize: (inst) => {
|
|
// Populate the default crop value into the form field.
|
|
let data = inst.getValue();
|
|
$cropField.value = [
|
|
data.x, data.y, data.width, data.height
|
|
].join(",");
|
|
}
|
|
});
|
|
}
|
|
});
|
|
reader.readAsDataURL(file);
|
|
};
|
|
|
|
// Set up drag/drop file upload events.
|
|
$body.addEventListener("dragenter", function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
$dropArea.classList.add("is-active");
|
|
});
|
|
$body.addEventListener("dragover", function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
$dropArea.classList.add("is-active");
|
|
});
|
|
$body.addEventListener("dragleave", function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
$dropArea.classList.remove("is-active");
|
|
});
|
|
$body.addEventListener("drop", function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
$dropArea.classList.remove("is-active");
|
|
|
|
// Grab the file.
|
|
let dt = e.dataTransfer;
|
|
let file = dt.files[0];
|
|
|
|
// Set the file on the input field too.
|
|
$file.files = dt.files;
|
|
|
|
onFile(file);
|
|
});
|
|
|
|
// Clear the answer in case of page reload.
|
|
$cropField.value = "";
|
|
|
|
$file.addEventListener("change", function() {
|
|
let file = this.files[0];
|
|
onFile(file);
|
|
});
|
|
});
|
|
{{end}}
|
|
|
|
// Alt Text helper.
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
let $altText = document.querySelector("#alt_text"),
|
|
$length = document.querySelector("#alt_text_length"),
|
|
maxLength = 5000;
|
|
|
|
$altText.maxLength = maxLength;
|
|
|
|
$altText.addEventListener("keydown", (e) => {
|
|
if ($altText.value.length >= maxLength) {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
let update = () => {
|
|
$length.innerHTML = `${$altText.value.length}/${maxLength}`;
|
|
};
|
|
|
|
$altText.addEventListener("keyup", update);
|
|
$altText.addEventListener("change", update);
|
|
update();
|
|
});
|
|
|
|
// EditPhoto only: a button to crop their photo to set as a profile pic.
|
|
function setProfilePhoto() {
|
|
let $begin = document.querySelector("#editphoto-begin-crop"),
|
|
$cropRow = document.querySelector("#editphoto-cropping"),
|
|
$preview = document.querySelector("#editphoto-preview")
|
|
$cropField = document.querySelector("#cropCoords"),
|
|
$intent = document.querySelector("#intent");
|
|
img = document.querySelector("#editphoto-img");
|
|
|
|
// Toggle the button display, from begin crop to the crop reset button.
|
|
$begin.style.display = 'none';
|
|
$cropRow.style.display = 'block';
|
|
|
|
// Set intent to profile-pic so when the form posts the crop coords will
|
|
// create a new profile pic for this user.
|
|
$intent.value = "profile-pic";
|
|
|
|
croppr = new Croppr(img, {
|
|
aspectRatio: 1,
|
|
minSize: [ 32, 32, 'px' ],
|
|
returnMode: 'real',
|
|
onCropStart: (data) => {
|
|
// console.log(data);
|
|
},
|
|
onCropMove: (data) => {
|
|
// console.log(data);
|
|
},
|
|
onCropEnd: (data) => {
|
|
// console.log(data);
|
|
$cropField.value = [
|
|
data.x, data.y, data.width, data.height
|
|
].join(",");
|
|
},
|
|
onInitialize: (inst) => {
|
|
// Populate the default crop value into the form field.
|
|
let data = inst.getValue();
|
|
$cropField.value = [
|
|
data.x, data.y, data.width, data.height
|
|
].join(",");
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
|
|
</div>
|
|
{{end}}
|