$images = $this->image->orderBy('created_at', 'desc')
->skip($page * $pageSize)->take($pageSize)->get();
foreach ($images as $image) {
- $image->thumbnail = $this->getThumbnail($image, 150, 150);
+ $this->loadSizes($image);
}
$hasMore = $this->image->orderBy('created_at', 'desc')
->skip(($page + 1) * $pageSize)->take($pageSize)->count() > 0;
return response()->json([
- 'images' => $images,
+ 'images' => $images,
'hasMore' => $hasMore
]);
}
+ /**
+ * Loads the standard thumbnail sizes for an image.
+ * @param Image $image
+ */
+ private function loadSizes(Image $image)
+ {
+ $image->thumbnail = $this->getThumbnail($image, 150, 150);
+ $image->display = $this->getThumbnail($image, 840, 0, true);
+ }
+
/**
* Get the thumbnail for an image.
- * @param $image
- * @param int $width
- * @param int $height
+ * If $keepRatio is true only the width will be used.
+ * @param $image
+ * @param int $width
+ * @param int $height
+ * @param bool $keepRatio
* @return string
*/
- public function getThumbnail($image, $width = 220, $height = 220)
+ public function getThumbnail($image, $width = 220, $height = 220, $keepRatio = false)
{
$explodedPath = explode('/', $image->url);
- array_splice($explodedPath, 4, 0, ['thumbs-' . $width . '-' . $height]);
+ $dirPrefix = $keepRatio ? 'scaled-' : 'thumbs-';
+ array_splice($explodedPath, 4, 0, [$dirPrefix . $width . '-' . $height]);
$thumbPath = implode('/', $explodedPath);
$thumbFilePath = public_path() . $thumbPath;
// Otherwise create the thumbnail
$thumb = ImageTool::make(public_path() . $image->url);
- $thumb->fit($width, $height);
+ if($keepRatio) {
+ $thumb->resize($width, null, function ($constraint) {
+ $constraint->aspectRatio();
+ $constraint->upsize();
+ });
+ } else {
+ $thumb->fit($width, $height);
+ }
// Create thumbnail folder if it does not exist
if (!file_exists(dirname($thumbFilePath))) {
$this->image->created_by = auth()->user()->id;
$this->image->updated_by = auth()->user()->id;
$this->image->save();
- $this->image->thumbnail = $this->getThumbnail($this->image, 150, 150);
+ $this->loadSizes($this->image);
return response()->json($this->image);
}
$image = $this->image->findOrFail($imageId);
$image->fill($request->all());
$image->save();
+ $this->loadSizes($image);
return response()->json($this->image);
}
"tests"
],
"dependencies": {
- "tinymce-dist": "~4.2.1",
+ "tinymce-dist": "~4.2.6",
"bootstrap": "~3.3.5",
"jquery-sortable": "~0.9.13",
"material-design-iconic-font": "~2.1.1"
<template>
<div id="image-manager">
- <div class="overlay" v-el="overlay" v-on="click: overlayClick" >
+ <div class="overlay" v-el="overlay" v-on="click: overlayClick">
<div class="image-manager-body">
<div class="image-manager-content">
<div class="image-manager-list">
<hr class="even">
<div v-show="dependantPages">
<p class="text-neg text-small">
- This image is used in the pages below, Click delete again to confirm you want to delete this image.
+ This image is used in the pages below, Click delete again to confirm you want to delete
+ this image.
</p>
<ul class="text-neg">
<li v-repeat="page: dependantPages">
</form>
</div>
<div class="image-manager-bottom">
- <button class="button pos anim fadeIn" v-show="selectedImage" v-on="click:selectButtonClick"><i class="zmdi zmdi-square-right"></i>Select Image</button>
+ <button class="button pos anim fadeIn" v-show="selectedImage" v-on="click:selectButtonClick"><i
+ class="zmdi zmdi-square-right"></i>Select Image
+ </button>
</div>
</div>
</div>
var Dropzone = require('dropzone');
module.exports = {
- data: function(){
+ data: function () {
return {
images: [],
hasMore: false,
selectedImage: false,
dependantPages: false,
deleteForm: {},
- token: document.querySelector('meta[name=token]').getAttribute('content')
+ token: document.querySelector('meta[name=token]').getAttribute('content'),
+ dataLoaded: false
}
},
created: function () {
- // Get initial images
- this.fetchData(this.page);
window.ImageManager = this;
},
show: function (callback) {
this.callback = callback;
this.$$.overlay.style.display = 'block';
+ // Get initial images if they have not yet been loaded in.
+ if (!this.dataLoaded) {
+ this.fetchData(this.page);
+ this.dataLoaded = true;
+ }
},
overlayClick: function (e) {
_this.images.splice(_this.images.indexOf(_this.selectedImage), 1);
_this.selectedImage = false;
$(_this.$$.imageTitle).showSuccess('Image Deleted');
- }).fail(function(jqXHR, textStatus) {
+ }).fail(function (jqXHR, textStatus) {
// Pages failure
- if(jqXHR.status === 400) {
+ if (jqXHR.status === 400) {
_this.dependantPages = jqXHR.responseJSON;
}
});
automatic_uploads: false,
valid_children: "-div[p|pre|h1|h2|h3|h4|h5|h6|blockquote]",
plugins: "image table textcolor paste link imagetools fullscreen code hr",
- toolbar: "undo redo | styleselect | bold italic underline strikethrough superscript subscript | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table image link hr | removeformat code fullscreen",
+ toolbar: "undo redo | styleselect | bold italic underline strikethrough superscript subscript | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table image-insert link hr | removeformat code fullscreen",
content_style: "body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}",
style_formats: [
{title: "Header 1", format: "h1"},
}
},
setup: function(editor) {
+
+ ( function() {
+ var wrap;
+
+ function hasTextContent( node ) {
+ return node && !! ( node.textContent || node.innerText );
+ }
+
+ editor.on( 'dragstart', function() {
+ var node = editor.selection.getNode();
+
+ if ( node.nodeName === 'IMG' ) {
+ wrap = editor.dom.getParent( node, '.mceTemp' );
+
+ if ( ! wrap && node.parentNode.nodeName === 'A' && ! hasTextContent( node.parentNode ) ) {
+ wrap = node.parentNode;
+ }
+ }
+ } );
+
+ editor.on( 'drop', function( event ) {
+ var dom = editor.dom,
+ rng = tinymce.dom.RangeUtils.getCaretRangeFromPoint( event.clientX, event.clientY, editor.getDoc() );
+
+ // Don't allow anything to be dropped in a captioned image.
+ if ( dom.getParent( rng.startContainer, '.mceTemp' ) ) {
+ event.preventDefault();
+ } else if ( wrap ) {
+ event.preventDefault();
+
+ editor.undoManager.transact( function() {
+ editor.selection.setRng( rng );
+ editor.selection.setNode( wrap );
+ dom.remove( wrap );
+ } );
+ }
+
+ wrap = null;
+ } );
+ } )();
+
+ // Image picker button
+ editor.addButton('image-insert', {
+ title: 'My title',
+ icon: 'image',
+ tooltip: 'Insert an image',
+ onclick: function() {
+ ImageManager.show(function(image) {
+ var html = '<p><a href="'+image.url+'" target="_blank">';
+ html += '<img src="'+image.display+'" alt="'+image.name+'">';
+ html += '</a></p>';
+ console.log(image);
+ editor.execCommand('mceInsertContent', false, html);
+ });
+ }
+ });
// Paste image-uploads
editor.on('paste', function(e) {
if(e.clipboardData) {