started building gallery widget
This commit is contained in:
commit
2ddcf21572
|
|
@ -0,0 +1,18 @@
|
||||||
|
# This file is for unifying the coding style for different editors and IDEs
|
||||||
|
# editorconfig.org
|
||||||
|
|
||||||
|
# WordPress Coding Standards
|
||||||
|
# https://make.wordpress.org/core/handbook/coding-standards/
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Output of `npm pack`
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Output of `wp-scripts plugin-zip`
|
||||||
|
*.zip
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
// This file is generated. Do not modify it manually.
|
||||||
|
return array(
|
||||||
|
'theatergf-gallery' => array(
|
||||||
|
'$schema' => 'https://schemas.wp.org/trunk/block.json',
|
||||||
|
'apiVersion' => 3,
|
||||||
|
'name' => 'theatergf/theatergf-gallery',
|
||||||
|
'version' => '0.1.0',
|
||||||
|
'title' => 'Gallery',
|
||||||
|
'category' => 'media',
|
||||||
|
'example' => array(
|
||||||
|
|
||||||
|
),
|
||||||
|
'supports' => array(
|
||||||
|
'html' => false
|
||||||
|
),
|
||||||
|
'textdomain' => 'theatergf-gallery',
|
||||||
|
'editorScript' => 'file:./index.js',
|
||||||
|
'editorStyle' => 'file:./index.css',
|
||||||
|
'style' => 'file:./style-index.css',
|
||||||
|
'render' => 'file:./render.php',
|
||||||
|
'viewScript' => 'file:./view.js'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||||
|
"apiVersion": 3,
|
||||||
|
"name": "theatergf/theatergf-gallery",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"title": "Gallery",
|
||||||
|
"category": "media",
|
||||||
|
"example": {},
|
||||||
|
"supports": {
|
||||||
|
"html": false
|
||||||
|
},
|
||||||
|
"textdomain": "theatergf-gallery",
|
||||||
|
"editorScript": "file:./index.js",
|
||||||
|
"editorStyle": "file:./index.css",
|
||||||
|
"style": "file:./style-index.css",
|
||||||
|
"render": "file:./render.php",
|
||||||
|
"viewScript": "file:./view.js"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
.wp-block-theatergf-theatergf-gallery{border:1px dotted red}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => 'cf9890b5e4d67862718c');
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
.wp-block-theatergf-theatergf-gallery{border:1px dotted red}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
(()=>{"use strict";var r,e={640(){const r=window.wp.blocks,e=window.wp.i18n,t=window.wp.blockEditor,o=window.ReactJSXRuntime,l=JSON.parse('{"UU":"theatergf/theatergf-gallery"}');(0,r.registerBlockType)(l.UU,{edit:function(){return(0,o.jsx)("p",{...(0,t.useBlockProps)(),children:(0,e.__)("Gallery – hello from the editor!","theatergf-gallery")})}})}},t={};function o(r){var l=t[r];if(void 0!==l)return l.exports;var a=t[r]={exports:{}};return e[r](a,a.exports,o),a.exports}o.m=e,r=[],o.O=(e,t,l,a)=>{if(!t){var i=1/0;for(p=0;p<r.length;p++){for(var[t,l,a]=r[p],n=!0,s=0;s<t.length;s++)(!1&a||i>=a)&&Object.keys(o.O).every(r=>o.O[r](t[s]))?t.splice(s--,1):(n=!1,a<i&&(i=a));if(n){r.splice(p--,1);var h=l();void 0!==h&&(e=h)}}return e}a=a||0;for(var p=r.length;p>0&&r[p-1][2]>a;p--)r[p]=r[p-1];r[p]=[t,l,a]},o.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={53:0,513:0};o.O.j=e=>0===r[e];var e=(e,t)=>{var l,a,[i,n,s]=t,h=0;if(i.some(e=>0!==r[e])){for(l in n)o.o(n,l)&&(o.m[l]=n[l]);if(s)var p=s(o)}for(e&&e(t);h<i.length;h++)a=i[h],o.o(r,a)&&r[a]&&r[a][0](),r[a]=0;return o.O(p)},t=globalThis.webpackChunktheatergf_gallery=globalThis.webpackChunktheatergf_gallery||[];t.forEach(e.bind(null,0)),t.push=e.bind(null,t.push.bind(t))})();var l=o.O(void 0,[513],()=>o(640));l=o.O(l)})();
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHP file to use when rendering the block type on the server to show on the front end.
|
||||||
|
*
|
||||||
|
* The following variables are exposed to the file:
|
||||||
|
* $attributes (array): The block attributes.
|
||||||
|
* $content (string): The block default content.
|
||||||
|
* $block (WP_Block): The block instance.
|
||||||
|
*
|
||||||
|
* @see https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/block-api/block-metadata.md#render
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<p <?php echo get_block_wrapper_attributes(); ?>>
|
||||||
|
<?php esc_html_e( 'Gallery – hello from a dynamic block!', 'theatergf-gallery' ); ?>
|
||||||
|
</p>
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
.wp-block-theatergf-theatergf-gallery{background-color:#21759b;color:#fff;padding:2px}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
.wp-block-theatergf-theatergf-gallery{background-color:#21759b;color:#fff;padding:2px}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<?php return array('dependencies' => array(), 'version' => '58813c89e11ed1cf4a36');
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
console.log("Hello World! (from theatergf-theatergf-gallery block)");
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"name": "theatergf-gallery",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": "Patrick Maschek",
|
||||||
|
"main": "build/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "wp-scripts build --webpack-copy-php --blocks-manifest",
|
||||||
|
"format": "wp-scripts format",
|
||||||
|
"lint:css": "wp-scripts lint-style",
|
||||||
|
"lint:js": "wp-scripts lint-js",
|
||||||
|
"packages-update": "wp-scripts packages-update",
|
||||||
|
"plugin-zip": "wp-scripts plugin-zip",
|
||||||
|
"start": "wp-scripts start --webpack-copy-php --blocks-manifest"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@wordpress/block-editor": "latest",
|
||||||
|
"@wordpress/blocks": "latest",
|
||||||
|
"@wordpress/i18n": "latest"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@wordpress/scripts": "^31.6.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
=== Gallery ===
|
||||||
|
Contributors: Patrick Maschek
|
||||||
|
Tags: block
|
||||||
|
Tested up to: 6.8
|
||||||
|
Stable tag: 0.1.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
== Description ==
|
||||||
|
|
||||||
|
This is the long description. No limit, and you can use Markdown (as well as in the following sections).
|
||||||
|
|
||||||
|
For backwards compatibility, if this section is missing, the full length of the short description will be used, and
|
||||||
|
Markdown parsed.
|
||||||
|
|
||||||
|
== Installation ==
|
||||||
|
|
||||||
|
This section describes how to install the plugin and get it working.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
1. Upload the plugin files to the `/wp-content/plugins/theatergf-gallery` directory, or install the plugin through the WordPress plugins screen directly.
|
||||||
|
1. Activate the plugin through the 'Plugins' screen in WordPress
|
||||||
|
|
||||||
|
|
||||||
|
== Frequently Asked Questions ==
|
||||||
|
|
||||||
|
= A question that someone might have =
|
||||||
|
|
||||||
|
An answer to that question.
|
||||||
|
|
||||||
|
= What about foo bar? =
|
||||||
|
|
||||||
|
Answer to foo bar dilemma.
|
||||||
|
|
||||||
|
== Screenshots ==
|
||||||
|
|
||||||
|
1. This screen shot description corresponds to screenshot-1.(png|jpg|jpeg|gif). Note that the screenshot is taken from
|
||||||
|
the /assets directory or the directory that contains the stable readme.txt (tags or trunk). Screenshots in the /assets
|
||||||
|
directory take precedence. For example, `/assets/screenshot-1.png` would win over `/tags/4.3/screenshot-1.png`
|
||||||
|
(or jpg, jpeg, gif).
|
||||||
|
2. This is the second screen shot
|
||||||
|
|
||||||
|
== Changelog ==
|
||||||
|
|
||||||
|
= 0.1.0 =
|
||||||
|
* Release
|
||||||
|
|
||||||
|
== Arbitrary section ==
|
||||||
|
|
||||||
|
You may provide arbitrary sections, in the same format as the ones above. This may be of use for extremely complicated
|
||||||
|
plugins where more information needs to be conveyed that doesn't fit into the categories of "description" or
|
||||||
|
"installation." Arbitrary sections will be shown below the built-in sections outlined above.
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
namespace TheaterGF\Gallery\Admin;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/gallery.php';
|
||||||
|
|
||||||
|
function admin_menu_init() {
|
||||||
|
|
||||||
|
if ( ! menu_page_url('theatergf', false) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_submenu_page(
|
||||||
|
'theatergf',
|
||||||
|
'Gallery',
|
||||||
|
'Gallery',
|
||||||
|
'manage_options',
|
||||||
|
'theatergf-gallery',
|
||||||
|
'TheaterGF\Gallery\Admin\admin_gallery_html'
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
add_action('admin_menu', 'TheaterGF\Gallery\Admin\admin_menu_init');
|
||||||
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
namespace TheaterGF\Gallery\Admin;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/gallery/html.php';
|
||||||
|
|
||||||
|
function gallery_app_menu_get_cb() {
|
||||||
|
return 'TheaterGF\Gallery\Admin\admin_gallery_html';
|
||||||
|
}
|
||||||
|
|
||||||
|
function gallery_app_init($hook) {
|
||||||
|
global $gallery_app_dir;
|
||||||
|
|
||||||
|
if ($hook !== 'theatergruppe_page_theatergf-gallery') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$gallery_app_dir = plugin_dir_url(__FILE__) . 'gallery';
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dependencies
|
||||||
|
*/
|
||||||
|
// Wordpress Media Library Dialog
|
||||||
|
wp_enqueue_media();
|
||||||
|
|
||||||
|
// Image Cropping Library
|
||||||
|
/*wp_enqueue_style(
|
||||||
|
'cropper-css',
|
||||||
|
'https://unpkg.com/cropperjs@2.1.0/dist/cropper.css',
|
||||||
|
array(),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
wp_enqueue_script(
|
||||||
|
'cropper-js',
|
||||||
|
'https://unpkg.com/cropperjs@2.1.0/dist/cropper.js',
|
||||||
|
array(),
|
||||||
|
null
|
||||||
|
);*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Own scripts
|
||||||
|
*/
|
||||||
|
wp_enqueue_style(
|
||||||
|
'theatergf-gallery-admin-css',
|
||||||
|
$gallery_app_dir . '/style.css'
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_enqueue_script(
|
||||||
|
'theatergf-gallery-admin-js',
|
||||||
|
$gallery_app_dir . '/script.js',
|
||||||
|
array( 'jquery', 'jcrop' )
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
add_action('admin_enqueue_scripts', 'TheaterGF\Gallery\Admin\gallery_app_init');
|
||||||
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
namespace TheaterGF\Gallery\Admin;
|
||||||
|
|
||||||
|
function admin_gallery_html($args) {
|
||||||
|
?>
|
||||||
|
<div class="wrap">
|
||||||
|
<h1>Gallery</h1>
|
||||||
|
|
||||||
|
<div class="theatergf gallery_app">
|
||||||
|
|
||||||
|
<div id="theatergf-editor" class="theatergf image-editor">
|
||||||
|
</div>
|
||||||
|
<button id="theatergf-select-image" class="button button-primary">Select image</button>
|
||||||
|
|
||||||
|
<div style="height: 15px"></div>
|
||||||
|
|
||||||
|
<div class="theatergf image-edit-wrap">
|
||||||
|
<canvas id="theatergf-image-editor"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,384 @@
|
||||||
|
|
||||||
|
const devicePixelRatio = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
|
class ImageCropper {
|
||||||
|
|
||||||
|
constructor(canvas) {
|
||||||
|
if (!(canvas instanceof HTMLCanvasElement)) {
|
||||||
|
throw TypeError('canvas must be a HTMLCanvasElement');
|
||||||
|
}
|
||||||
|
this._preview = canvas;
|
||||||
|
this._preview_ctx = canvas.getContext('2d');
|
||||||
|
this._preview_ctx.reset();
|
||||||
|
|
||||||
|
const dimensions = this._preview.getBoundingClientRect();
|
||||||
|
console.log(dimensions);
|
||||||
|
console.log(this._preview.width, this._preview.height);
|
||||||
|
|
||||||
|
this._preview.width = dimensions.width * devicePixelRatio;
|
||||||
|
this._preview.height = dimensions.height * devicePixelRatio;
|
||||||
|
this._preview_ctx.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
showImage(image_src) {
|
||||||
|
this._image = new Image();
|
||||||
|
this._image.src = image_src;
|
||||||
|
|
||||||
|
this._image.addEventListener('load', (e) => {
|
||||||
|
|
||||||
|
const dimensions = this._preview.getBoundingClientRect();
|
||||||
|
|
||||||
|
const scale = {
|
||||||
|
x: dimensions.width / this._image.naturalWidth,
|
||||||
|
y: dimensions.height / this._image.naturalHeight
|
||||||
|
}
|
||||||
|
const ratio = Math.min(scale.x, scale.y);
|
||||||
|
|
||||||
|
const position = {
|
||||||
|
x: (dimensions.width - this._image.naturalWidth * ratio) / 2,
|
||||||
|
y: (dimensions.height - this._image.naturalHeight * ratio) / 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
this._preview_ctx.drawImage(this._image, position.x, position.y, this._image.naturalWidth * ratio, this._image.naturalHeight * ratio);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
doCrop() {
|
||||||
|
this._shadow = document.createElement('canvas');
|
||||||
|
this._shadow.style.display = 'none';
|
||||||
|
this._shadow_ctx = canvas.getContext('2d');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*jQuery(document).ready( ($) => {
|
||||||
|
|
||||||
|
let wp_file_selector_frame;
|
||||||
|
let image_cropper;
|
||||||
|
|
||||||
|
$('#theatergf-select-image').on('click', (event) => {
|
||||||
|
|
||||||
|
// don't open browser file select
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (wp_file_selector_frame) {
|
||||||
|
wp_file_selector_frame.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_file_selector_frame = wp.media({
|
||||||
|
title: 'Select Image',
|
||||||
|
button: {
|
||||||
|
text: 'Use Image'
|
||||||
|
},
|
||||||
|
multiple: false
|
||||||
|
});
|
||||||
|
|
||||||
|
wp_file_selector_frame.on('select', () => {
|
||||||
|
const file = wp_file_selector_frame.state().get('selection').first().toJSON();
|
||||||
|
|
||||||
|
image_cropper = new ImageCropper(document.getElementById('theatergf-image-editor'));
|
||||||
|
//image_cropper.showImage('http://localhost:8000/wp-content/uploads/2026/03/Kishon002.jpg');
|
||||||
|
|
||||||
|
image_cropper.showImage(file.url);
|
||||||
|
//document.getElementById('theatergf-image-preview').src = file.url;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
wp_file_selector_frame.open();
|
||||||
|
});
|
||||||
|
});*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ResizableBox {
|
||||||
|
constructor(element, aspectRatio = null) {
|
||||||
|
this.element = element;
|
||||||
|
this.aspectRatio = aspectRatio;
|
||||||
|
|
||||||
|
this.mouseStart = {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
this.elemStart = {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: element.style.width,
|
||||||
|
height: element.style.height,
|
||||||
|
corner_pos: {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.direction = undefined;
|
||||||
|
|
||||||
|
const dragMouseMove = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const offset = {
|
||||||
|
x: event.clientX - this.mouseStart.x,
|
||||||
|
y: event.clientY - this.mouseStart.y
|
||||||
|
};
|
||||||
|
|
||||||
|
const delta = {...offset};
|
||||||
|
|
||||||
|
if (this.direction && aspectRatio) {
|
||||||
|
|
||||||
|
const {anchor, sign} = (() => {
|
||||||
|
switch (this.direction) {
|
||||||
|
case 'nw':
|
||||||
|
return {
|
||||||
|
anchor: {
|
||||||
|
x: this.elemStart.left + this.elemStart.width,
|
||||||
|
y: this.elemStart.top + this.elemStart.height
|
||||||
|
},
|
||||||
|
sign: {
|
||||||
|
x: -1,
|
||||||
|
y: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'ne':
|
||||||
|
return {
|
||||||
|
anchor: {
|
||||||
|
x: this.elemStart.left,
|
||||||
|
y: this.elemStart.top + this.elemStart.height
|
||||||
|
},
|
||||||
|
sign: {
|
||||||
|
x: +1,
|
||||||
|
y: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'sw':
|
||||||
|
return {
|
||||||
|
anchor: {
|
||||||
|
x: this.elemStart.left + this.elemStart.width,
|
||||||
|
y: this.elemStart.top
|
||||||
|
},
|
||||||
|
sign: {
|
||||||
|
x: -1,
|
||||||
|
y: +1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'se':
|
||||||
|
return {
|
||||||
|
anchor: {
|
||||||
|
x: this.elemStart.left,
|
||||||
|
y: this.elemStart.top
|
||||||
|
},
|
||||||
|
sign: {
|
||||||
|
x: +1,
|
||||||
|
y: +1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
const px = this.elemStart.corner_pos.x + offset.x
|
||||||
|
const py = this.elemStart.corner_pos.y + offset.y
|
||||||
|
|
||||||
|
const dx = sign.x * (px - anchor.x)
|
||||||
|
const dy = sign.y * (py - anchor.y)
|
||||||
|
|
||||||
|
const sh = dx/this.elemStart.width
|
||||||
|
const sv = dy/this.elemStart.height
|
||||||
|
|
||||||
|
const dv = Math.abs(dx - this.elemStart.width)
|
||||||
|
const dh = Math.abs(dy - this.elemStart.height)
|
||||||
|
|
||||||
|
const s = (dv > dh) ? sv : sh
|
||||||
|
|
||||||
|
delta.x = sign.x * (s * this.elemStart.width - this.elemStart.width)
|
||||||
|
delta.y = sign.y * (s * this.elemStart.height - this.elemStart.height)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(this.direction) {
|
||||||
|
case 'nw':
|
||||||
|
this.element.style.left = (this.elemStart.left + delta.x) + "px";
|
||||||
|
this.element.style.top = (this.elemStart.top + delta.y) + "px";
|
||||||
|
this.element.style.width = (this.elemStart.width - delta.x) + "px";
|
||||||
|
this.element.style.height = (this.elemStart.height - delta.y) + "px";
|
||||||
|
break;
|
||||||
|
case 'ne':
|
||||||
|
this.element.style.top = (this.elemStart.top + delta.y) + "px";
|
||||||
|
this.element.style.width = (this.elemStart.width + delta.x) + "px";
|
||||||
|
this.element.style.height = (this.elemStart.height - delta.y) + "px";
|
||||||
|
break;
|
||||||
|
case 'sw':
|
||||||
|
this.element.style.left = (this.elemStart.left + delta.x) + "px";
|
||||||
|
this.element.style.width = (this.elemStart.width - delta.x) + "px";
|
||||||
|
this.element.style.height = (this.elemStart.height + delta.y) + "px";
|
||||||
|
break;
|
||||||
|
case 'se':
|
||||||
|
this.element.style.width = (this.elemStart.width + delta.x) + "px";
|
||||||
|
this.element.style.height = (this.elemStart.height + delta.y) + "px";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// moving is the default
|
||||||
|
default:
|
||||||
|
this.element.style.left = (this.elemStart.left + offset.x) + "px";
|
||||||
|
this.element.style.top = (this.elemStart.top + offset.y) + "px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const dragMouseUp = (_) => {
|
||||||
|
this.element.classList.remove("moving");
|
||||||
|
this.direction = undefined
|
||||||
|
document.removeEventListener('mousemove', dragMouseMove);
|
||||||
|
document.removeEventListener('mouseup', dragMouseUp);
|
||||||
|
};
|
||||||
|
|
||||||
|
const dragMouseDown = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this.mouseStart.x = event.clientX;
|
||||||
|
this.mouseStart.y = event.clientY;
|
||||||
|
|
||||||
|
this.elemStart.left = this.element.offsetLeft;
|
||||||
|
this.elemStart.top = this.element.offsetTop;
|
||||||
|
this.elemStart.width = this.element.offsetWidth;
|
||||||
|
this.elemStart.height = this.element.offsetHeight;
|
||||||
|
|
||||||
|
this.direction = [...event.target.classList].find(c => ["nw","ne","sw","se"].includes(c));
|
||||||
|
|
||||||
|
switch (this.direction) {
|
||||||
|
case 'nw':
|
||||||
|
this.elemStart.corner_pos.x = this.element.offsetLeft;
|
||||||
|
this.elemStart.corner_pos.y = this.element.offsetTop;
|
||||||
|
break;
|
||||||
|
case 'ne':
|
||||||
|
this.elemStart.corner_pos.x = this.element.offsetLeft + this.element.offsetWidth;
|
||||||
|
this.elemStart.corner_pos.y = this.element.offsetTop;
|
||||||
|
break;
|
||||||
|
case 'sw':
|
||||||
|
this.elemStart.corner_pos.x = this.element.offsetLeft;
|
||||||
|
this.elemStart.corner_pos.y = this.element.offsetTop + this.element.offsetHeight;
|
||||||
|
break;
|
||||||
|
case 'se':
|
||||||
|
this.elemStart.corner_pos.x = this.element.offsetLeft + this.element.offsetWidth;
|
||||||
|
this.elemStart.corner_pos.y = this.element.offsetTop + this.element.offsetHeight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.element.classList.add('moving');
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', dragMouseMove);
|
||||||
|
document.addEventListener('mouseup', dragMouseUp);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.element.addEventListener('mousedown', dragMouseDown);
|
||||||
|
|
||||||
|
this.createHandles();
|
||||||
|
}
|
||||||
|
|
||||||
|
createHandles() {
|
||||||
|
const handles = this.element.querySelectorAll('.handle');
|
||||||
|
for (const handle of handles) {
|
||||||
|
this.element.removeChild(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
const neHandle = document.createElement('div');
|
||||||
|
neHandle.classList.add('handle', 'ne');
|
||||||
|
|
||||||
|
const nwHandle = document.createElement('div');
|
||||||
|
nwHandle.classList.add('handle', 'nw');
|
||||||
|
|
||||||
|
const seHandle = document.createElement('div');
|
||||||
|
seHandle.classList.add('handle', 'se');
|
||||||
|
|
||||||
|
const swHandle = document.createElement('div');
|
||||||
|
swHandle.classList.add('handle', 'sw');
|
||||||
|
|
||||||
|
this.element.appendChild(neHandle);
|
||||||
|
this.element.appendChild(nwHandle);
|
||||||
|
this.element.appendChild(seHandle);
|
||||||
|
this.element.appendChild(swHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRect() {
|
||||||
|
return new DOMRect(this.element.offsetLeft, this.element.offsetTop, this.element.offsetWidth, this.element.offsetHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Editor {
|
||||||
|
|
||||||
|
constructor(editorElement, aspectRatio) {
|
||||||
|
this._editor = editorElement;
|
||||||
|
this.aspectRatio = aspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadImage(url) {
|
||||||
|
const imgElement = new Image()
|
||||||
|
imgElement.classList.add("editor-image");
|
||||||
|
imgElement.src = url;
|
||||||
|
|
||||||
|
this._editor.replaceChildren(imgElement);
|
||||||
|
|
||||||
|
const that = this;
|
||||||
|
imgElement.addEventListener('load', (_) => {
|
||||||
|
|
||||||
|
const size = {
|
||||||
|
width: imgElement.offsetWidth,
|
||||||
|
height: imgElement.offsetHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
if (size.width > size.height * that.aspectRatio) {
|
||||||
|
size.width = size.height * that.aspectRatio;
|
||||||
|
} else {
|
||||||
|
size.height = size.width / that.aspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
that._createSelectionBox(size.width, size.height);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_createSelectionBox(width, height) {
|
||||||
|
const selector = document.createElement('div');
|
||||||
|
selector.classList.add('selector');
|
||||||
|
|
||||||
|
selector.style.width = (width - 1) + "px";
|
||||||
|
selector.style.height = (height - 1) + "px";
|
||||||
|
|
||||||
|
this._cutSelector = selector;
|
||||||
|
this._editor.appendChild(selector);
|
||||||
|
|
||||||
|
this._cutArea = new ResizableBox(selector, width/height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
jQuery(document).ready( ($) => {
|
||||||
|
let wp_file_selector_frame = null;
|
||||||
|
let editor = new Editor(document.querySelector("#theatergf-editor"), 4/3);
|
||||||
|
|
||||||
|
$("#theatergf-select-image").on("click", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (wp_file_selector_frame) {
|
||||||
|
wp_file_selector_frame.open();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_file_selector_frame = wp.media({
|
||||||
|
title: 'Select Image',
|
||||||
|
button: {
|
||||||
|
text: 'Use Image'
|
||||||
|
},
|
||||||
|
multiple: false
|
||||||
|
});
|
||||||
|
|
||||||
|
wp_file_selector_frame.on('select', () => {
|
||||||
|
const file = wp_file_selector_frame.state().get('selection').first().toJSON();
|
||||||
|
|
||||||
|
editor.loadImage(file.url);
|
||||||
|
});
|
||||||
|
|
||||||
|
wp_file_selector_frame.open();
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
|
||||||
|
.theatergf {
|
||||||
|
|
||||||
|
.image-editor {
|
||||||
|
aspect-ratio: 2 / 1;
|
||||||
|
width: 75%;
|
||||||
|
|
||||||
|
background-color: lightgray;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.editor-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
position: absolute;
|
||||||
|
border: blue 1px solid;
|
||||||
|
|
||||||
|
/*top: 50%;
|
||||||
|
left: 50%;*/
|
||||||
|
/*transform: translate(-50%, -50%);*/
|
||||||
|
|
||||||
|
cursor: grab;
|
||||||
|
|
||||||
|
&.moving {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
.handle {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
|
||||||
|
border: blue 1px solid;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
/*transform: translate(-50%, -50%);*/
|
||||||
|
|
||||||
|
&.nw {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
transform: translate(-1px, -1px);
|
||||||
|
cursor: nwse-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.ne {
|
||||||
|
top: 0;
|
||||||
|
left: 100%;
|
||||||
|
transform: translate(calc(-100% + 1px), -1px);
|
||||||
|
cursor: nesw-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.sw {
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
transform: translate(-1px, calc(-100% + 1px));
|
||||||
|
cursor: nesw-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.se {
|
||||||
|
top: 100%;
|
||||||
|
left: 100%;
|
||||||
|
transform: translate(calc(-100% + 1px), calc(-100% + 1px));
|
||||||
|
cursor: nwse-resize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-edit-wrap {
|
||||||
|
aspect-ratio: 2 / 1;
|
||||||
|
width: 75%;
|
||||||
|
height: 75%;
|
||||||
|
|
||||||
|
background-color: gray;
|
||||||
|
|
||||||
|
#theatergf-image-editor {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#theatergf-image-editor-shadow {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||||
|
"apiVersion": 3,
|
||||||
|
"name": "theatergf/theatergf-gallery",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"title": "Gallery",
|
||||||
|
"category": "media",
|
||||||
|
"example": {},
|
||||||
|
"supports": {
|
||||||
|
"html": false
|
||||||
|
},
|
||||||
|
"textdomain": "theatergf-gallery",
|
||||||
|
"editorScript": "file:./index.js",
|
||||||
|
"editorStyle": "file:./index.css",
|
||||||
|
"style": "file:./style-index.css",
|
||||||
|
"render": "file:./render.php",
|
||||||
|
"viewScript": "file:./view.js"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/**
|
||||||
|
* Retrieves the translation of text.
|
||||||
|
*
|
||||||
|
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/
|
||||||
|
*/
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React hook that is used to mark the block wrapper element.
|
||||||
|
* It provides all the necessary props like the class name.
|
||||||
|
*
|
||||||
|
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
|
||||||
|
*/
|
||||||
|
import { useBlockProps } from '@wordpress/block-editor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
|
||||||
|
* Those files can contain any CSS code that gets applied to the editor.
|
||||||
|
*
|
||||||
|
* @see https://www.npmjs.com/package/@wordpress/scripts#using-css
|
||||||
|
*/
|
||||||
|
import './editor.scss';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The edit function describes the structure of your block in the context of the
|
||||||
|
* editor. This represents what the editor will render when the block is used.
|
||||||
|
*
|
||||||
|
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit
|
||||||
|
*
|
||||||
|
* @return {Element} Element to render.
|
||||||
|
*/
|
||||||
|
export default function Edit() {
|
||||||
|
return (
|
||||||
|
<p { ...useBlockProps() }>
|
||||||
|
{ __( 'Gallery – hello from the editor!', 'theatergf-gallery' ) }
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
/**
|
||||||
|
* The following styles get applied inside the editor only.
|
||||||
|
*
|
||||||
|
* Replace them with your own styles or remove the file completely.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.wp-block-theatergf-theatergf-gallery {
|
||||||
|
border: 1px dotted #f00;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* Registers a new block provided a unique name and an object defining its behavior.
|
||||||
|
*
|
||||||
|
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
|
||||||
|
*/
|
||||||
|
import { registerBlockType } from '@wordpress/blocks';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
|
||||||
|
* All files containing `style` keyword are bundled together. The code used
|
||||||
|
* gets applied both to the front of your site and to the editor.
|
||||||
|
*
|
||||||
|
* @see https://www.npmjs.com/package/@wordpress/scripts#using-css
|
||||||
|
*/
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import Edit from './edit';
|
||||||
|
import metadata from './block.json';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Every block starts by registering a new block type definition.
|
||||||
|
*
|
||||||
|
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
|
||||||
|
*/
|
||||||
|
registerBlockType( metadata.name, {
|
||||||
|
/**
|
||||||
|
* @see ./edit.js
|
||||||
|
*/
|
||||||
|
edit: Edit,
|
||||||
|
} );
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHP file to use when rendering the block type on the server to show on the front end.
|
||||||
|
*
|
||||||
|
* The following variables are exposed to the file:
|
||||||
|
* $attributes (array): The block attributes.
|
||||||
|
* $content (string): The block default content.
|
||||||
|
* $block (WP_Block): The block instance.
|
||||||
|
*
|
||||||
|
* @see https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/block-api/block-metadata.md#render
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<p <?php echo get_block_wrapper_attributes(); ?>>
|
||||||
|
<?php esc_html_e( 'Gallery – hello from a dynamic block!', 'theatergf-gallery' ); ?>
|
||||||
|
</p>
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
/**
|
||||||
|
* The following styles get applied both on the front of your site
|
||||||
|
* and in the editor.
|
||||||
|
*
|
||||||
|
* Replace them with your own styles or remove the file completely.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.wp-block-theatergf-theatergf-gallery {
|
||||||
|
background-color: #21759b;
|
||||||
|
color: #fff;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* Use this file for JavaScript code that you want to run in the front-end
|
||||||
|
* on posts/pages that contain this block.
|
||||||
|
*
|
||||||
|
* When this file is defined as the value of the `viewScript` property
|
||||||
|
* in `block.json` it will be enqueued on the front end of the site.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* {
|
||||||
|
* "viewScript": "file:./view.js"
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If you're not making any changes to this file because your project doesn't need any
|
||||||
|
* JavaScript running in the front-end, then you should delete this file and remove
|
||||||
|
* the `viewScript` property from `block.json`.
|
||||||
|
*
|
||||||
|
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#view-script
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
console.log( 'Hello World! (from theatergf-theatergf-gallery block)' );
|
||||||
|
/* eslint-enable no-console */
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: Gallery
|
||||||
|
* Version: 0.1.0
|
||||||
|
* Requires at least: 6.8
|
||||||
|
* Requires PHP: 7.4
|
||||||
|
* Author: Patrick Maschek
|
||||||
|
* Text Domain: theatergf-gallery
|
||||||
|
* Requires Plugins: theatergf-core
|
||||||
|
*
|
||||||
|
* @package Theatergf
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TheaterGF\Gallery;
|
||||||
|
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit; // Exit if accessed directly.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the block(s) metadata from the `blocks-manifest.php` and registers the block type(s)
|
||||||
|
* based on the registered block metadata. Behind the scenes, it registers also all assets so they can be enqueued
|
||||||
|
* through the block editor in the corresponding context.
|
||||||
|
*
|
||||||
|
* @see https://make.wordpress.org/core/2025/03/13/more-efficient-block-type-registration-in-6-8/
|
||||||
|
* @see https://make.wordpress.org/core/2024/10/17/new-block-type-registration-apis-to-improve-performance-in-wordpress-6-7/
|
||||||
|
*/
|
||||||
|
function block_init() {
|
||||||
|
wp_register_block_types_from_metadata_collection( __DIR__ . '/build', __DIR__ . '/build/blocks-manifest.php' );
|
||||||
|
}
|
||||||
|
add_action( 'init', 'TheaterGF\Gallery\block_init' );
|
||||||
|
|
||||||
|
if ( is_admin() ) {
|
||||||
|
require_once __DIR__ . '/src/admin/admin.php';
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue