Closed mohamedveron closed 7 years ago
Hi @mohamedveron,
Thanks for the kind words. So if you can't drag the crop region around that sounds like a JS issue, could you let me know what browser/version you are using and also can you check to see if there's any error output in the console please?
Ant
I use the latest version of Firefox and chrome and there is no errors in inspector .
@mohamedveron are you able to move the crop pins on the demo page here: http://getcontenttools.com/demo
I'm using the latest stable release of chromium currently and I can click on the blue pins and drag them when I select the crop button on the demo page.
it is working in both browsers
Can you post your code that's not working gist or JS fiddle, or send me a zip of the code so I can see if I can spot what's going wrong?
And the following code which i use to crop image .. // Check if a crop region has been defined by the user if (dialog.cropRegion()) { alert(dialog.cropRegion()); formData.append('crop', dialog.cropRegion()); }
OK that's just the uploader code, the image uploader code you write shouldn't impact on whether crop pins can be dragged or the crop tool can be selected.
Can I just confirm is the issue that you can't select the crop tool and change the crop region using the pins in the browser, and your questions doesn't refer to a server side issue?
Yes, there is no server side issue, i can insert image in server and ajax return images path and size successfully .
OK well I'm a little stumped then since the uploader code shouldn't impact on the crop region code, the uploader code only queries for the final crop region size, it doesn't implement the code to activate or resize the crop region, and like you say the demo page works correctly for you. Any chance of a live link so I can see the issue in action you can email to me if you prefer (ant@getme.co.uk)?
I will but first i need to ask if the following code is enough to crop images..
if (dialog.cropRegion()) { formData.append('crop', dialog.cropRegion()); }
And following screen shot may help ..
So that's enough to collect the crop region data, however it might help you if I provide a working handler example, I only have a CoffeeScript example but it should show you an approach we've used for a live application:
class ImageUploader
# An image uploader for the in-page site editor.
constructor: (dialog) ->
# Initialize the dialog to support image uploads
# The image dialog the uploader is providing functionality for
@_dialog = dialog
# The image being edited (when the dialog is populated)
@_image = null
# The operations applied to the image
@_imageOps = []
# The XHR used to upload an image (when the dialog is uploading)
@_xhr = null
# Listen to key events from the dialog and assign handlers to each
@_dialog.addEventListener 'imageuploader.cancelupload', () =>
@_onCancelUpload()
@_dialog.addEventListener 'imageuploader.clear', () =>
@_onClear()
@_dialog.addEventListener 'imageuploader.fileready', (ev) =>
@_onFileReady(ev.detail().file)
@_dialog.addEventListener 'imageuploader.rotateccw', () =>
@_onRotateCCW()
@_dialog.addEventListener 'imageuploader.rotatecw', () =>
@_onRotateCW()
@_dialog.addEventListener 'imageuploader.save', () =>
@_onSave()
# Event handlers
_onCancelUpload: () ->
# Handle an upload being cancelled
# Stop the upload
if @_xhr
@_xhr.upload.removeEventListener 'progress', @_xhrProgress
@_xhr.removeEventListener 'readystatechange', @_xhrComplete
@_xhr.abort()
# Set the dialog to empty
@_dialog.state('empty')
_onClear: () ->
# Handle the current image being cleared
@_dialog.clear()
@_image = null
@_imageOps = null
_onFileReady: (file) ->
# Handle a file being selected by the user
# Set the dialog state to uploading
@_dialog.progress(0)
@_dialog.state('uploading')
# Build the form data to post to the server
formData = new FormData()
formData.append('__file__', file)
# Build a request to send the file
@_xhr = new XMLHttpRequest();
# Handle progress
@_xhrProgress = (ev) =>
@_dialog.progress((ev.loaded / ev.total) * 100)
@_xhr.upload.addEventListener('progress', @_xhrProgress)
# Handle completion
@_xhrComplete = (ev) =>
readyState = ev.target.readyState
text = ev.target.responseText
status = ev.target.status
# Look for done response
if readyState != 4
return
# Clear the XHR reference
@_xhr = null
# Handle the result of the upload
if parseInt(status) is 200
response = JSON.parse(text)
# Handle failed response
if response.status is 'fail'
new ContentTools.FlashUI('no')
return
# Handle successful response
@_image = response.payload.image
@_dialog.populate(@_image.url, @_image.size)
else
# Handle error response
new ContentTools.FlashUI('no')
@_xhr.addEventListener('readystatechange', @_xhrComplete)
# Send the file
@_xhr.open('POST', '/cms/image-upload', true)
@_xhr.send(formData)
_onRotateCCW: () ->
# Handle a request by the user to rotate the image counter-clockwise
@_imageOps.push(['Rotate', {'direction': 'ccw'}])
@_applyOps (image) =>
@_image = image
@_dialog.populate(@_image.url, @_image.size)
_onRotateCW: () ->
# Handle a request by the user to rotate the image clockwise
@_imageOps.push(['Rotate', {'direction': 'cw'}])
@_applyOps (image) =>
@_image = image
@_dialog.populate(@_image.url, @_image.size)
_onSave: () ->
# Handle the user saving the image
cropRegion = @_dialog.cropRegion()
# Check if the crop is the full size of the image, if so no need to
# apply a crop.
if JSON.stringify(cropRegion) is JSON.stringify([0, 0, 1, 1])
@_dialog.save(@_image.url, @_image.size, @_buildImageAttrs())
return
# Apply a crop to the image before inserting it into the page.
crop = [
[cropRegion[1], cropRegion[0]],
[cropRegion[3], cropRegion[0]],
[cropRegion[3], cropRegion[2]],
[cropRegion[1], cropRegion[2]]
]
@_imageOps.push(['Crop', {'crop_marks': crop}])
@_applyOps (image) =>
@_image = image
@_dialog.save(@_image.url, @_image.size, @_buildImageAttrs())
# Private methods
_applyOps: (callback) ->
# Apply the current list of image ops to the image, any callback will be
# called on successful completion with the new image information.
# Send the save data to the CMS
payload = new FormData();
payload.append('uid', @_image.uid)
payload.append('ops', JSON.stringify(@_imageOps))
onStateChange = (ev) ->
# Check if the request is finished
unless ev.target.readyState == 4
return
# Finished saving the content
if ev.target.status is 200
text = ev.target.responseText
response = JSON.parse(text)
# Call the callback
callback(response.payload.image)
# Save was successful, notify the user with a flash
new ContentTools.FlashUI('ok');
else
# Save failed, notify the user with a flash
new ContentTools.FlashUI('no');
xhr = new XMLHttpRequest()
xhr.addEventListener('readystatechange', onStateChange)
xhr.open('POST', '/cms/image-upload')
xhr.send(payload)
_buildImageAttrs: () ->
# Build a list of attributes to save the image with
return {
'alt': @_image.alt,
'data-uid': @_image.uid,
'data-ce-max-width': @_image.max_size
}
# Class methods
@createImageUploader: (dialog) ->
return new ImageUploader(dialog)
window.ImageUploader = ImageUploader
But it still give me array of Nan when i make an alert for crop region..
if (dialog.cropRegion()) {
alert(dialog.cropRegion());
formData.append('crop', dialog.cropRegion());
}
If you don't attempt to crop the image does the method return [0, 0, 1, 1]
?
Just to confirm I've tested (in Chrome) calling cropRegion
using the sandox demo with the latest CT release (1.3.1 - just to check you're using the latest release I assume?). The output is the expected array of 4 floats (between 0-1).
Without access to a demo or your code it's really difficult to investigate the issue as I can't reproduce it myself.
yes it returns [0, 0, 1, 1]
But i didn't use sandbox.js file i just use content-tools.min.js and followed the Getting start and image upload tutorials .
Is sandbox.js file contain crop methods which is not in content-tool.js ?
OK so then it would appear the issue is specific to the CropMarksUI
component and it not being able to query the position of the crop pins/handles in order to return a valid crop region. Here's the code that builds the crop region: https://github.com/GetmeUK/ContentTools/blob/master/src/scripts/ui/dialogs/image.coffee#L402
I suspect what's happening here is that the values in _bounds
are not valid numbers, and they are in turn set when you set the width and height of the image, so when you call populate
you should pass in an image size which is an array with 2 values [width, height]. I suspect your not passing it an array with 2 values, can you check that when you call populate
the value of image.size
is actually an array containing the width and height?
No the sandbox JS uses the CT library in the same directory.
It worked with me when sandbox.js imported in my js file. Thanks and sorry for wasting your time.
And i will check what is the wrong by myself :)
No problem - it's often tricky to find these problems :) I hope this points you in the right direction and you can resolve the issue. If I can be any further help though I'm happy to help where I can :)
I had similar issue. The "crop feature" didn't work on client side. Now fixed!
The problem was with server-side response while 'imageuploader.fileready'
event called an /upload-image
server action. Response was invalid. Instead of expected eg.: {size: [320, 200], url: "/uploads/something.png"}
, by mistake the size was returned with a file size ;-)
I think also for others this a bit misleading name size
instead of "dimensions" could lead to similar issue ;-)
When I fixed the "size" response, the crop feature worked perfectly!
Hello, First of all thank you for this amazing library.
I can't crop images in dialog i followed the http://getcontenttools.com/tutorials/handling-image-uploads tutorial and the following link contain the image upload function ----> http://ideone.com/br0wlV
i can't update the crop Region and crop buttons didn't work with me. Thanks in advance.