Graphical glitch using JCrop - javascript

I'm having serious troubles implementing Jcrop. I'll show the code regarding Jcrop implementation:
$("#crop-mini").Jcrop({
onChange : updatePositions,
onSelect : updatePositions,
boxWidth : 500,
boxHeight : 400,
keySupport : false,
setSelect : [0, 0, 999999, 999999],
minSize : [10, 10]
});
Where #crop-mini is the <img> tag containing the image. updatePositions is just a function that... updates the selection positions. Pretty straightforward:
function updatePositions(coords)
{
$(".x").val(coords.x);
$(".y").val(coords.y);
$(".w").val(coords.w);
$(".h").val(coords.h);
};
I upload an image, write its url into the <img> tag, fire a fancybox and call JCrop. However, when I resize the selection box, boom, this glitch appears:
It looks like the selected content shows the same image being deformed from positions coords.y (coords is the current selection position) to coords.h+coords.y, and from 0 to coords.w. If I put the selection touching the left corner, you would see the whole image.
By the way, cropping works as expected, and the real coordinates are being passed, so I happen to think that the problem is within the presentation, not the processing. Did I do anything wrong?

This happens when you have max-width set in your css:
img {
max-width: 100%
}
Just add the following rule to fix it:
.image-version img {
max-width: none;
}
Where .image-version is a css class of the element wrapping <img> with id #crop-mini.

Related

Targeting a specific div with html2canvas

I'm using Hertzen's html2canvas.js, and tried to adjust the example code so that it targets a specific div instead of the entire body of a document:
html2canvas(document.body, {
onrendered: function(canvas) {
document.body.appendChild(canvas);
}
});
A sample of what I'm trying to accomplish is here: https://jsfiddle.net/ununkg3a/
On clicking the "Save PNG" button, I want to append an image of the jQuery generated squares that I'm targeting in a specific div. In the code, it appears that it's appending something, but it doesn't have a height. When I try to set a height with the output, it still doesn't work as expected.
Is it not possible to accomplish something like this? Whenever I change document.body to another element, the screenshot doesn't render anymore, although it does render when I change it back to document.body. Someone told me that I'd have to crop the image with js, but that seems a little hacky.
It can: it's the first attribute.
(fiddle)
Example:
html2canvas(document.getElementById('test')).then(function(canvas) {
document.body.appendChild(canvas);
});
In your example, canvas2html can't find out the height of your div. Because of that it falls back to 0px height, so you won't see anything.
Give width to the #art then you can count the height manually and use that.
Mathematic example:
art_square_width = 10px
art_square_height = 10px
art_square_amount = 500
art_width = 250px
art_height = art_width / (art_width / art_square_width) * art_square_height = 200px
(fiddle)

Can't get hidden image to display with .show()

I'm using the vimeo api to slide a video off the screen after it finishes playing. Underneath the video player, hidden, I have an image that says 'replay'. The image though is slightly bigger than the player so I want to hide the image via .hide() or display: none in the css and then show it after the animation of the video player completes.
Here's my js:
$(document).ready(function() {
$(".vimeo-container img").hide();
$('iframe.vimeo').each(function(){
Froogaloop(this).addEvent('ready', ready);
});
function ready(playerID){
Froogaloop(playerID).addEvent('finish', onFinish);
}
function onFinish(playerID) {
var player = "#" + playerID;
$(player).animate({width: "0%"}, 750, function() {
$(player).next("img").show();
});
}
});
So the first line is hiding the image. And then when the onFinish function completes I'm trying to show() the image, but it won't work. I should note that when I reverse it and do:
$(player).next("img").hide();
it works.
Here's my HTML:
%section#container1
.row.video-left
.large-8.columns
.vimeo-container
.flex-video.widescreen.vimeo
%iframe.vimeo#player1{allowfullscreen: "", frameborder: "0", height: "225", mozallowfullscreen: "", src: "http://player.vimeo.com/video/60122989?api=1&player_id=player1", webkitallowfullscreen: "", width: "400"}
= image_tag "behind1.png", class: "behind1"
And CSS:
.vimeo-container {
position: relative;
.behind1 {
margin-top: -27em;
}
I've also tried setting display: none in the css, but that wont work either. Not sure what I'm missing.
Thanks.
EDIT
function onFinish(playerID) {
var player = "#" + playerID;
$(player).animate({width: "0%"}, 750, function() {
console.log($(player));
$(player).next().show();
});
}
When I log out ($(player) it returns:
And when I log out console.log($(player).next()); it logs out the image that I am trying to show.
According to the jQuery documentation on the animate method here:
Note: Unlike shorthand animation methods such as .slideDown() and .fadeIn(), the .animate() method does not make hidden elements visible as part of the effect. For example, given $( "someElement" ).hide().animate({height: "20px"}, 500), the animation will run, but the element will remain hidden.
I had a similar need in a project and what worked for me there was to set the z-index of the element I wanted to hide to be less than that of the background. Then, when I wanted to show (or, in your case, animate) I could apply the jQuery methods to the element as if they were hidden (by increasing the z-index so that the element becomes visible), yet not incur the undefined behaviour of attempting to manipulate a hidden element.
Another option would be to move the element off the screen by way of a negative (x, y) coordinate and work from there. I'm not sure which visually would be more appealing in your use case but mention it for completeness.

change css on scroll event w/ requestAnimation Frame

I want to change the background color of in-viewport elements (using overflow: scroll)
So here was my first attempt:
http://jsfiddle.net/2YeZG/
As you see, there is a brief flicker of the previous color before the new color is painted. Others have had similar problems.
Following the HTML5 rocks instructions, I tried to introduce requestAnimationFrame to fix this problem to no avail:
http://jsfiddle.net/RETbF/
What am I doing wrong here?
Here is a simpler example showing the same problem: http://jsfiddle.net/HJ9ng/
Filed bug with Chromium here: http://code.google.com/p/chromium/issues/detail?id=151880
if it is only the background color, well why don't you just change the parent background color to red and once it scroll just change it to pink?
I change your CSS to that
#dad
{
overflow-y: scroll;
overflow-x: hidden;
width: 100px;
height: 600px;
background-color:red;
}​
I remove some of you Jquery and change it to this
dad.bind('scroll', function() {
dad.css('background-color', 'pink');
});
And I remove this line
iChild.css('backgroundColor', 'red');
But is the Red color it is important that won't work for sure http://jsfiddle.net/2YeZG/5/
I like Manuel's Solution.
But even though I don't get what you're exactly trying to do, I want to point out a few things.
In your fiddle code, I saw that you included Paul Irish's Shim for requestAnimationFrame.
But you never use it.
(It's basically a reliable setTimeOut, nothing else) it's from frame based animations.)
So since you just want to change some CSS properties, I don't see why you would need it. Even if you want transitions, you should rely on CSS transitions.
Other than that your code could look something like
dad.bind('scroll', function() {
dad.css('background-color', 'pink');
eachElemNameHere.css('background-color','randomColor');
});
Also you should ideally not use something like that if you can help it. You should just add and remove class names and add all these properties in your CSS. Makes it work faster.
Also, again I don't quite get it, but you could use the jQuery function to find out each elements' position from the top to have better control.
Your problem seems to be that you only change the background color of the elements which have already been scrolled into view. Your code expects that the browser waits for your code to handle the scroll event before the browser redraws its view. This is most probably not a guarantee given by the HTML spec. That's why it flickers.
What you should do instead is to change the elements which are going to be scrolled into view. This is related to off screen rendering or double buffering as it is called in computer games programming. You build your scene off screen and copy the finished scene to the visible frame buffer.
I modified your first JSFiddle to include a multiplier for the height of the scroll area: http://jsfiddle.net/2YeZG/13/.
dad.bind('scroll', function() {
// new: query multiplier from input field (for demonstration only) and print message
var multiplier = +($("#multiplier")[0].value);
$("#message")[0].innerHTML=(multiplier*100)-100 + "% of screen rendering";
// your original code
var newScrollY = newScrollY = dad.scrollTop();
var isForward = newScrollY > oldScrollY;
var minVal = bSearch(bots, newScrollY, true);
// new: expand covered height by the given multiplier
// multiplier = 1 is similar to your code
// multiplier = 2 would be complete off screen rendering
var newScrollYHt = newScrollY + multiplier * dadHeight;
// your original code (continued)
var maxVal;
for (maxVal = minVal; maxVal < botsLen; maxVal++) {
var nxtTopSide = tops[maxVal];
if (nxtTopSide >= newScrollYHt) {
break;
}
}
maxVal = Math.min(maxVal, botsLen);
$(dadKids.slice(minVal, maxVal)).css('background', 'pink');
});
Your code had a multiplier of 1, meaning that you update the elements which are currently visible (100% of scroll area height). If you set the multiplier to 2, you get complete off screen updates for all your elements. The browser updates enough elements to the new background color so that even a 100% scroll would show updated elements. Since the browser seldom scrolls 100% of the area in one step (depends of the operating system and the scroll method!), it may be sufficient to reduce the multiplier to e.g. 1.5 (meaning 50% off screen rendering). On my machine (Google Chrome, Mac OS X with touch pad) I cannot produce any flicker if the multiplier is 1.7 or above.
BTW: If you do something more complicated than just changing the background color, you should not do it again and again. Instead you should check whether the element has already been updated and perform the change only afterwards.

Draggable element in VML get stuck when size change (height, width) in IE 8

I'm having issue with VML (which I use as fallback for svg)
I use jQuery UI draggable to let user be able to move an element around. The problem occurs when I resize the image (which is a v:image) by changing the style attribute of height and width.
What happen at this point is that the element get stuck at the left top corner of it's container and cannot be dragged anymore.
A strange thing is that when I ask for the position (top, left) of the draggable element in the JavaScript console, I get value, and those values change when I click and drag - even though the element isn't visually moving...
Anyone run into this problem before?
Here's where I change then size of my element.
$($image)
.css({
'width' : zoomInPx_width + "px",
'height' : zoomInPx_height + "px"
});
The draggable is set pretty straight forward
$($image).draggable({
drag: function () { /*callback here*/ }
})
Finaly I manage to make this work.
Seems that VML crash on IE 8 when we change size of a draggable element. So, I had to destroy the element and recreate it from scratch when sliding occurs...
That's not really performant, but that's the only fix to work for me up here.
By the way, .detach() didn't work, you have to destroy it and recreate it from scratch.
You can get some info there too: http://www.acumen-corp.com/Blog/tabid/298/EntryId/26/Using-jqueryRotate-ui-draggable-and-resizable-images-in-IE7-IE8-and-any-other-browser.aspx
on my application I used this code:
var $cloned_image = $($image).clone().get(0);
$($image).remove();
// need add draggable again
$($cloned_image).draggable();
document.getElementById('k').appendChild($cloned_image);
$image = $cloned_image;

TinyMCE width and height disobedient!

According to the (conflicting) documentation of TinyMCE, the editor takes on the size of the textarea (or other) element that it replaces. It also says that you can set the size of the editor by specifying { height: '123', width: '123' } in the init method.
I have tried BOTH and still get only one result - the editor resizes itself to (how it remembers is beyond me) what it was the last time a user resized it.
Its saves the last size because of the theme settings. You can turn it off by using the following
$('textarea.tinymce').tinymce({
theme_advanced_resizing: true,
theme_advanced_resizing_use_cookie : false,
I know all about this, it is very annoying.
Adding this to any loaded CSS file fixed the width for me (I just put it in the global css, not in any of the TinyMCE css files, I did not test with height):
.mceEditor > table {
width:/* my width */ !important;
}
This would affect all instances, which was fine in my case. You can target the toolbar itself with .mceToolbar
You kind of do want TinyMCE to resize the textarea, so it can be wide enough to fit all the toolbar icons.
Here is my fix.
It works also for multiple instances of TinyMCE editors (init() with 'height' property works only for the first instance, so it's a workaround to achieve a fixed or minimum height of the editor box).
.mceEditor td.mceIframeContainer iframe {
min-height: 350px !important;
}
.mceEditor table {
height: auto !important;
}
Although there are a lot of good suggestions here I found the answer by reading the question. There is NO problem with height or width so why all these work arounds with CSS or writing functions, the method in the docs works.
The original challenge was about resizing, the author never said the height or width didn't work, it just didn't do what he/she expected - it was only stated as quoted below:
"the editor resizes itself to (how it remembers is beyond me) what it was the last time a user resized it."
Saidul Islam answered the question correctly and to take it one step further Stuart went on to describe how to turn off the cookies. If you need to set the height and width do it when in init() and be done. You can read more here:
https://www.tinymce.com/docs/configure/editor-appearance/#min_height
Sizing the input area in both height and width works as outlined below.
tinymce.init({
selector: '.profileTextArea',
plugins : 'advlist autolink link image lists charmap print preview code',
min_height: 400
});
tinyMCE.init({
mode : "exact",
.....
mode : "exact" will disable the ability to resize grid by drag
Yes, this is very annoying. I wrote my own function to adjust the height to the given input. You may modify it to set your height/width as you wish:
resizeIframe: function(frameid) {
var frameid = frameid ? frameid : this.editor.id+'_ifr';
var currentfr=document.getElementById(frameid);
if (currentfr && !window.opera){
currentfr.style.display="block";
if (currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight) { //ns6 syntax
currentfr.height = currentfr.contentDocument.body.offsetHeight + 26;
}
else if (currentfr.Document && currentfr.Document.body.scrollHeight) { //ie5+ syntax
currentfr.height = currentfr.Document.body.scrollHeight;
}
styles = currentfr.getAttribute('style').split(';');
for (var i=0; i<styles.length; i++) {
if ( styles[i].search('height:') ==1 ){
styles.splice(i,1);
break;
}
};
currentfr.setAttribute('style', styles.join(';'));
}
},
im setting width and height to editor area like this
<style>
#content{width: 620px; height: 500px;}
</style>
<textarea name="content" id="content" cols="50" rows="15"></textarea>
I noticed that a containing table was enforcing widths, and also the icon set are td's, so there's a minimum width they'll collapse down to, so if you have many icons in a single row - it could be messing all over your widths.
Sort of related SO question of mine, ended up being quite related to your problem: Able to float td elements consistently?
I found the TinyMCE text-area (called '.mceContentBody' in my theme) too small and awkwardly margined in the new post content area.
In my theme there's a css file called editor-style. I changed the width (to 98%) yet since TinyMCE uses cookies to remember the editor size, the CSS changes weren't sticking. After CLEARING MY BROWSER'S CACHE, the CSS width/margin changes took effect. Finally. Gah.
Add a 'body_id' using tinymce.init and then use that id in 'content_css' to give the editor the desired css behavior. Like so:
tinymce.init({
selector: "textarea",
content_css: '/css/app.css',
body_id: 'new-journal-editor'
});
And then in app.css:
#new-journal-editor {
height: 123px;
width: 123px;
}
I am facing the same problem but I end up doing this
#tinymce-textarea_ifr {
min-height: 500px !important;
}
.mce-tinymce {
width: 96% !important;
margin: 0 auto !important;
}
I find the best method to restrict the width tinyMCE 4+ textarea is to wrap the textarea in a new div or span tag. Then apply the width to that. This way you get use percentage widths instead of fixed px. if you want to adjust height edit the rows="15" value.
example:
<div style="width:90%!important;" ><textarea name="content"cols="100" rows="15" class="mceEditor" id="content"><?php echo $content;?></textarea></div>

Categories