Saving new crops made to media item from overlay (Umbraco 7) - javascript

I have an image cropper overlay that is being displayed for a media item selected from a media picker. I am able to display the media item and make changes to its crops just fine, but I am not sure how I go about saving my changes.
This is the overlay in question, without the saving functionality:
$scope.remove = function (index) {
$scope.overlay = {
mediaId: $scope.images.udi,
saving: false,
show: true, //controls whether to show the overlay or not
value: $scope.images[0].metaData.umbracoFile.Value,
config: $scope.images[0].metaData.umbracoFile.Value,
view: '/App_Plugins/Our.Umbraco.OutCrop/cropper.html',
close: function (oldModel) { //when the overlay is closed, dont show
$scope.overlay.show = false;
},
title: 'Image Crops',
submitButtonLabel: 'Save Crops',
submit: function (model) { //when user clicks save crops button
$scope.overlay.saving = true;
$scope.overlay.show = false;
//do savings...
}
}
When i press the submit button I need to have the new crops saved to the media item. The values the overlay uses to display the current crops are located in the "metaData.umbracoFile.Value" of the image. Only a single image is able to be selected.

Related

fabricjs change cursor for every object

I created some objects with fabric js and added different cursors for them if the user hovers with his mouse over the object. i want to add a function which changes the cursor for the whole canvas and all its objects and then changes it back to its default values (so the cursor settings for the objects and the canvas).
is there a way to do this simple? or do i have to set the cursor for every object manually?
I got a small jsFiddle for this: https://jsfiddle.net/bxgox7cr/14/
If you click on the button "change Cursor", the cursor is changed to a crosshair, but when you move your mose over the lines or circles, it is changed to their settings. I want the cursor to stay as a crosshair. After pressing "default Cursor" all the settings should be set back, so the cursor should use the special settings for lines and circles.
the main functionality is in this 2 functions:
$('#button').click(function() {
canvas.defaultCursor = 'crosshair';
});
$('#button2').click(function() {
canvas.defaultCursor = 'default';
});
I might save the default values for every object and then change them back after the click of button2, but this seems to be a difficult solution, so I'm hoping there might be an easier way.
Just add to your code this event:
canvas.on('mouse:over', function(event){
if (event.target != null)
event.target.hoverCursor = canvas.defaultCursor;
}
});
On each object you will reset 'hover' cursor what you set for whole canvas.
Updated:
If you need reset to default you have to keep track of original cursors for each object. You need something like this:
$('#button').click(function() {
changeCursor('crosshair');
});
$('#button2').click(function() {
resetCursor();
});
var cursors = {canvasDefault: canvas.defaultCursor,
canvasDefault: 'default',
object:[
{objectType: 'circle',
hoverCursor: 'move'},
{objectType: 'line',
hoverCursor: 'ns-resize'}
]
};
function changeCursor(cursor){
canvas.forEachObject(function(obj){
for (var i in cursors.object){
if (cursors.object[i].objectType == obj.type){
obj.hoverCursor = cursor;
}
}
canvas.defaultCursor = cursor;
});
}
function resetCursor(){
canvas.forEachObject(function(obj){
for (var i in cursors.object){
if (cursors.object[i].objectType == obj.type){
obj.hoverCursor = cursors.object[i].hoverCursor;
}
}
canvas.defaultCursor = cursors.canvasDefault;
});
}

How to lock slider and prevent updating of values with mouse into dat.GUI menu

I try to implement a way to prevent the updating of values with mouse (actually when the three.js animation has started, launched with a click on button).
For the moment, I have the following dat.GUI menu:
Once "start" button is clicked, I would like to prevent user from modifying with mouse the parameters "Rotation x" and "Rotation y".
Here is the concerned part of code for this menu:
// Create GUI
var gui = new dat.GUI({
autoplace: false,
width: 350,
height: 9 * 32 - 1
});
var params = {
GreatCircle : '',
Rotationx : torusRotationInitX,
Rotationy : torusRotationInitY,
StartingVector : '',
ComponentVectorTheta : 15.0,
ComponentVectorPhi : 15.0,
CovariantDerivativeVector : '',
ComponentCovariantDerivativeTheta : 15.0,
ComponentCovariantDerivativePhi : 15.0
};
// Set parameters for GUI
gui.add(params, 'GreatCircle').name('Great Circle ');
controllerRotationx = gui.add(params, 'Rotationx', 0, 2*Math.PI, 0.001).name('Rotation x ');
controllerRotationy = gui.add(params, 'Rotationy', 0, 2*Math.PI, 0.001).name('Rotation y ');
...
When I click on reset button, I call the following function:
// Reset Button
resetButton.onclick = function ResetParameters() {
...
// Reinitialize parameters into gui
params.Rotationx = torusRotationInitX;
params.Rotationy = torusRotationInitY;
for (var i in gui.__controllers) {
gui.__controllers[i].updateDisplay();
}
render();
}
I don't know if there is an option for controller to lock these sliders which usually change their values. Is it possible?
Update 1
Maybe I could wrapper the dat.GUI menu into a div and make this div not clickable, is it a solution?
Update 2
I tried to apply the method used on Method for disabling a button in dat.gui?
Following this solution, I have added the extension into dat.gui, just after:
dat.controllers.FunctionController = (function (Controller, dom, common) {
...
});
The following added code snippet is:
function blockEvent(event)
{
event.stopPropagation();
}
Object.defineProperty(dat.controllers.FunctionController.prototype, "disabled", {
get: function()
{
return this.domElement.hasAttribute("disabled");
},
set: function(value)
{
if (value)
{
this.domElement.setAttribute("disabled", "disabled");
this.domElement.addEventListener("click", blockEvent, true);
}
else
{
this.domElement.removeAttribute("disabled");
this.domElement.removeEventListener("click", blockEvent, true);
}
},
enumerable: true
});
Is extension code well located into dat.GUI source?
Then, I set the property "disabled" into my code to prevent user from sliding "controllerRotationx" with mouse (once start button is pressed):
if (animation)
controllerRotationx.__li.disabled = true;
Unfortunately, my method doesn't work : when animation is started, I can still move the slider contained into "controllerRotationx".
I saw that above link (Method for disabling a button in dat.gui?), this was about a button and not for a slider, does it change anything for my case?
I didn't find an explicit controller for the slider.
I would do this. The slider is not a form element, there's nothing to disable in the traditional w3c sense. Luckily we can use pointer-events and disable it properly as if it were a form element using just public dat.gui properties.
var speeder = menu.add(text, 'speed', -5, 5);
speeder.domElement.style.pointerEvents = "none"
speeder.domElement.style.opacity = .5;
The solution given by #Radio works pretty well. But, with sliders, the slider is a sibling of the text box's DOM element. We need to disable pointer events on the div which contains all the controls (and which is not exposed directly by dat.gui). So,
var speeder = menu.add(text, 'speed', -5, 5);
// disables the text box
speeder.domElement.style.pointerEvents = "none"
// disables all controller elements related to "speeder"
speeder.domElement.parentElement.style.pointerEvents = 'none'
When the Start button is pressed, set:
controllerRotationx.__li.setAttribute( "style", "display: none" );
thanks for tips
on my side i hack the Common controller
so able to chainning.
gui.add(this, '_screenW').disable(true);
Common.extend(controller, {
disable: function disable(v) {
this.domElement.style.pointerEvents = v?"none":"auto";
this.domElement.style.opacity = v?.5:1;
return controller;
},

Recent Camera gets overrided with the default image

I have an image grid, which was designed to have Add more button, when clicked on it. A new image placeholder should appear with a default image, when clicked on it the camera gets invoked and should update the default image with the picture taken. In my case, the camera picture is not getting updated but the default picture stays. When clicked on the add more, instead of the default picture the recent camera picture is getting appeared. I think there is a problem with rendering part of the code.
Here is my code
var Summary = React.createClass({
getInitialState: function(){
return {
picTriggers: [],
number:0,
image:"https://www.bignerdranch.com/img/blog/2014/07/Button-2.png"
}
},
camera: function(){
var that = this;
var image = this.state.image;
navigator.camera.getPicture(onSuccess, onFail, { quality: 50,
destinationType: Camera.DestinationType.DATA_URL
});
function onSuccess(imageData) {
console.log(imageData);
var finalimage = "data:image/jpeg;base64," + imageData;
that.setState({image: finalimage});
}
function onFail(message) {
alert('Failed because: ' + message);
}
},
newButton: function(){
var number = this.state.number;
number = number+1;
var picTriggers = this.state.picTriggers;
picTriggers.push(<img id={"div"+number} src={this.state.image} onClick={this.camera} className="addpicture"/>);
this.setState({picTriggers: picTriggers, number:number});
},
render: function(){
return(
<div>
{this.state.picTriggers}
<button onClick={this.newButton}>
{this.state.number>0?"Add More":"Add a picture"}
</button>
<button className="uploadselected"> Upload Selected </button>
</div>);
}
});
If I'm following this correctly, the flow here looks like:
First render: Add a picture button is rendered
If that button is clicked, a default image is shown via #newButton
If that image is clicked, the #camera function gets an image asynchronously and updates state with the image.
This will trigger #render. But you haven't done anything at this point to add a new item to picTriggers with the new image, so the old image displays.
When you click Add More, it runs #newButton again and you get your image rendered.
I think you could make your life much easier by just maintaining an array of imgSrcs instead of an array of rendered components. When you get the camera image, add to the array:
var finalImage = "data:image/jpeg;base64," + imageData;
// Better not to mutate state directly, so make a new array
// with slice, dropping the default image
var imgSrcs = this.state.imgSrcs.slice(0, -1);
imgSrcs.push(finalImage);
this.setState({ imgSrcs: imgSrcs });
And in #newButton, you just add the default image to the end of the array:
var imgSrcs = this.state.imgSrcs.concat([this.state.defaultImage]);
this.setState({ imgSrcs: imgSrcs });
Now you have a simple rendering problem, rendering a list of images, instead of a hard state problem, making sure your pre-rendered components are in sync each time #render is called.

Angular-leaflet-directive Custom HTML popup

I'm attempting to create a custom popup while using the angular-leaflet-directive. I'm opening the popup from the leaflet.draw on:create event. Here:
map.on('draw:created', function(e) {
layer = e.layer;
drawnItems.addLayer(layer);
var newComment = "Enter Comment";
var newID = "ID";
var newGeoJsonFeat = layer.toGeoJSON();
newGeoJsonFeat.properties = {"comment":newComment, "id":newID};
console.log(newGeoJsonFeat);
onEachFeature(newGeoJsonFeat,layer);
layer.openPopup();
});
Then I'm using #blackjid's logic as seen here: https://github.com/tombatossals/angular-leaflet-directive/issues/238 to bind the custom popup
function onEachFeature(feature, layer) {
// Create get the view template
var popupContent = '<div ng-include="\'partials/popup_newfeat.html\'"></div>';
console.log("assigning popup");
// Bind the popup
// HACK: I have added the stream in the popup options
layer.bindPopup(popupContent,{
closeButton: false,
maxHeight: 300,
feature: feature
});
};
$scope.$on('leafletDirectiveMap.popupopen', function(event, leafletEvent){
// Create the popup view when is opened
var feature = leafletEvent.leafletEvent.popup.options.feature;
var newScope = $scope.$new();
newScope.stream = feature;
$compile(leafletEvent.leafletEvent.popup._contentNode)(newScope);
});
Long story short, Everything works fine except the popup container isn't resizing properly to fit the new content. The height seems right, but the width is off.
I tried using:
.leaflet-popup-content {
width:auto !important;
}
Which will probably suffice, but this causes the popup anchor to shift to the bottom left of the popup for some reason. AutoPan is also broken when clicking near the top of the map.
Does anyone know where and how I can get popup.update() to fire? I believe thats what needs to happen, but I don't know where to implement it. I've tried calling it after layer.openPopup() like so:
onEachFeature(newGeoJsonFeat,layer);
layer.openPopup();
layer.getPopup().update();
});
But that doesn't seem to do anything. Any help is greatly appreciated!
You need to use the 'leafletEvent'. Try this:
myApp.controller('YourController', ['$scope', 'leafletEvent', function($scope) {
// after all your crazy custom popup stuff ...
leafletData.getMap().then(function(map) {
layer.getPopup().update();
});
}]);
I ended up storing the image width in the properties of the GeoJson, and then setting the minWidth to that value in the bindPopup function.
layer.bindPopup(popupContent,{
closeButton: true,
closeOnClick: false,
minWidth: feature.properties.width,
autoPanPadding: L.point(20,20),
keepInView: false,
feature: feature
});

Highcharts: Add a custom image button

I want to add and image button on highcharts.
So far, I have successfully created a image button and have attached a click event on it.
But problem is that, the image (sun.png) is on left side of chart and image button is right aligned ( the default position of toolbar). Any fix for this ?
exporting: {
buttons: {
popUpBtn: {
symbol: 'url(images/sun.png)',
_titleKey: 'popUpBtnTitle',
x: -10,
symbolFill: '#B5C9DF',
hoverSymbolFill: '#779ABF',
onclick: function () {
alert('ad');
popUpChart($(this));
}
},
exportButton: {
enabled: false
},
printButton: {
enabled: false
}
}
}
Also, if there are other methods to add an image in chart which have click event, those methods are welcomed too.
Finally, I figured it out like this.
May be it will help others.
function callback($this){
var img = $this.renderer.image('images/zoom_icon.png',$this.chartWidth-40,5,40,12);
img.add();
img.css({'cursor':'pointer'});
img.attr({'title':'Pop out chart'});
img.on('click',function(){
// prcessing after image is clicked
});
}
new Highcharts.Chart(charts.params,callback);
// where charts.params is object which contains options for chart

Categories

Resources