CROPPER JS Get cropper canvas not working with larger files - javascript

I am using https://github.com/fengyuanchen/cropperjs/ but it has a problem in getCroppedCanvas function ,
It's working just fine with small images but not showing when it comes to larger images
result.appendChild(cropper.getCroppedCanvas());
I am using this live example https://fengyuanchen.github.io/cropperjs/examples/upload-cropped-image-to-server.html; source code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Cropper.js</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css">
<link rel="stylesheet" href="../css/cropper.css">
<style>
.label {
cursor: pointer;
}
.progress {
display: none;
margin-bottom: 1rem;
}
.alert {
display: none;
}
.img-container img {
max-width: 100%;
}
</style>
</head>
<body>
<div class="container">
<h1>Upload cropped image to server</h1>
<label class="label" data-toggle="tooltip" title="Change your avatar">
<img class="rounded" id="avatar" src="https://avatars0.githubusercontent.com/u/3456749?s=160" alt="avatar">
<input type="file" class="sr-only" id="input" name="image" accept="image/*">
</label>
<div class="progress">
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
</div>
<div class="alert" role="alert"></div>
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalLabel">Crop the image</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="img-container">
<img id="image" src="https://avatars0.githubusercontent.com/u/3456749">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="crop">Crop</button>
</div>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.bundle.min.js"></script>
<script src="https://fengyuanchen.github.io/cropperjs/js/cropper.js"></script>
<script>
window.addEventListener('DOMContentLoaded', function () {
var avatar = document.getElementById('avatar');
var image = document.getElementById('image');
var input = document.getElementById('input');
var $progress = $('.progress');
var $progressBar = $('.progress-bar');
var $alert = $('.alert');
var $modal = $('#modal');
var cropper;
$('[data-toggle="tooltip"]').tooltip();
input.addEventListener('change', function (e) {
var files = e.target.files;
var done = function (url) {
input.value = '';
image.src = url;
$alert.hide();
$modal.modal('show');
};
var reader;
var file;
var url;
if (files && files.length > 0) {
file = files[0];
if (URL) {
done(URL.createObjectURL(file));
} else if (FileReader) {
reader = new FileReader();
reader.onload = function (e) {
done(reader.result);
};
reader.readAsDataURL(file);
}
}
});
$modal.on('shown.bs.modal', function () {
cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 3,
});
}).on('hidden.bs.modal', function () {
cropper.destroy();
cropper = null;
});
document.getElementById('crop').addEventListener('click', function () {
var initialAvatarURL;
var canvas;
$modal.modal('hide');
if (cropper) {
canvas = cropper.getCroppedCanvas({
width: 160,
height: 160,
});
initialAvatarURL = avatar.src;
avatar.src = canvas.toDataURL();
$progress.show();
$alert.removeClass('alert-success alert-warning');
canvas.toBlob(function (blob) {
var formData = new FormData();
formData.append('avatar', blob, 'avatar.jpg');
$.ajax('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
data: formData,
processData: false,
contentType: false,
xhr: function () {
var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function (e) {
var percent = '0';
var percentage = '0%';
if (e.lengthComputable) {
percent = Math.round((e.loaded / e.total) * 100);
percentage = percent + '%';
$progressBar.width(percentage).attr('aria-valuenow', percent).text(percentage);
}
};
return xhr;
},
success: function () {
$alert.show().addClass('alert-success').text('Upload success');
},
error: function () {
avatar.src = initialAvatarURL;
$alert.show().addClass('alert-warning').text('Upload error');
},
complete: function () {
$progress.hide();
},
});
});
}
});
});
</script>
</body>
</html>
the cropper script is in: https://fengyuanchen.github.io/cropperjs/js/cropper.js

Using croppiejs helped me solve this issue. To utilize Croppie with a preview, you just set the value of an html image element to croppie's base64 result:
First create croppie instance:
var cropperlg = new Croppie(document.getElementById('croppie-lg'), {
viewport: {
width: 400
height: 800
},
boundary: {
height: 500
width: 1000
}
});
This bit of code binds croppie to an image and executes the crop on click.
EDIT: I simplified the code for a more basic example.
cropperlg.bind({
url: '/images/someimg.jpg'
});
$('#crop-btn').on('click', (e) => {
cropperlg.result({
type: 'canvas',
size: { width: 1000, height: 400 }
}).then(function(result) {
$('#cropped-img').attr('src', result);
})
});
You should be able to figure it out from here.

this worked for me
var cropper = $('#cropper-image').cropper('getCroppedCanvas', {
// Limit max sizes
maxWidth: 4096,
maxHeight: 4096,
});
After setting this, it worked well on both mobile and desktop.

Related

How to use Cropper.js with images that are already uploaded to my server instead of cropping and then uploading image to correct folder

Hi I'm new to Js so not really sure how to figure this one out. I have a user pictures gallery on my website and I use simple php file upload script to upload pictures for my users. I have a button under each picture to set given image as a profile pic but I'm in need of getting this picture cropped to correct aspect ratio so I tried using Cropper.js. The problem is I can't find a way to pass an image to cropper.js. else than creating an upload form. I've spent days trying to google the way I could use cropperjs without this upload form but can't seem to find a way. It's my first question on stackoverflow any help would be appreciated.
<!DOCTYPE html>
<html>
<head>
<title>PHP Crop Image Before Upload using Cropper JS</title>
<meta name="_token" content="{{ csrf_token() }}">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha256-WqU1JavFxSAMcLP2WIOI+GB2zWmShMI82mTpLDcqFUg=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.css" integrity="sha256-jKV9n9bkk/CTP8zbtEtnKaKf+ehRovOYeKoyfthwbC8=" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.js" integrity="sha256-CgvH7sz3tHhkiVKh05kSUgG97YtzYNnWt6OXcmYzqHY=" crossorigin="anonymous"></script>
</head>
<style type="text/css">
img {
display: block;
max-width: 100%;
}
.preview {
overflow: hidden;
width: 160px;
height: 160px;
margin: 10px;
border: 1px solid red;
}
.modal-lg{
max-width: 1000px !important;
}
</style>
<body>
<div class="container">
<h1>PHP Crop Image Before Upload using Cropper JS - NiceSnippets.com</h1>
<form method="post">
<input type="file" name="image" class="image">
</form>
</div>
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalLabel">PHP Crop Image Before Upload using Cropper JS - NiceSnippets.com</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="img-container">
<div class="row">
<div class="col-md-8">
<img id="image" src="https://avatars0.githubusercontent.com/u/3456749">
</div>
<div class="col-md-4">
<div class="preview"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="crop">Crop</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var $modal = $('#modal');
var image = document.getElementById('image');
var cropper;
$("body").on("change", ".image", function(e){
var files = e.target.files;
var done = function (url) {
image.src = url;
$modal.modal('show');
};
var reader;
var file;
var url;
if (files && files.length > 0) {
file = files[0];
if (URL) {
done(URL.createObjectURL(file));
} else if (FileReader) {
reader = new FileReader();
reader.onload = function (e) {
done(reader.result);
};
reader.readAsDataURL(file);
}
}
});
$modal.on('shown.bs.modal', function () {
cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 3,
preview: '.preview'
});
}).on('hidden.bs.modal', function () {
cropper.destroy();
cropper = null;
});
$("#crop").click(function(){
canvas = cropper.getCroppedCanvas({
width: 160,
height: 160,
});
canvas.toBlob(function(blob) {
url = URL.createObjectURL(blob);
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
var base64data = reader.result;
$.ajax({
type: "POST",
dataType: "json",
url: "upload.php",
data: {image: base64data},
success: function(data){
console.log(data);
$modal.modal('hide');
alert("success upload image");
}
});
}
});
})
</script>
</body>
</html>

Cropping and uploading image with Croppie jquery plugin

cropping and uploading image using Croppie plugin working fine sample code as follows
<html lang="en">
<head>
<title>PHP and jQuery - Crop Image and Upload using Croppie plugin</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.2/croppie.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.2/croppie.js"></script>
<meta name="csrf-token" content="{{ csrf_token() }}">
<style>
.croppie-container .cr-vp-circle
{
border-radius:0
}
.cr-slider-wrap
{
display:none
}
</style>
</head>
<body>
<div class="container">
<div class="card" style="max-height: 500px;">
<div class="card-header bg-info" style="display:none">PHP and jQuery - Crop Image and Upload using Croppie plugin</div>
<div class="card-body">
<div class="row">
<div class="col-md-4 text-center">
<div id="upload-demo"></div>
</div>
<div class="col-md-4" style="padding:5%;">
<strong>Select image to crop:</strong>
<input type="file" id="image">
<button class="btn btn-success btn-block btn-upload-image" style="margin-top:2%">Upload Image</button>
</div>
<div class="col-md-4" style="background: #9d9d9d;">
<div id="preview-crop-image" style="background: #fff;
width: 200px;
margin: 50px 72px;
height: 200px;"></div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var resize = $('#upload-demo').croppie({
enableExif: true,
enableOrientation: true,
viewport: { // Default { width: 100, height: 100, type: 'square' }
width: 200,
height: 200,
type: 'square' //square
},
boundary: {
width: 300,
height: 300
}
});
$('#image').on('change', function () {
var reader = new FileReader();
reader.onload = function (e) {
resize.croppie('bind',{
url: e.target.result
}).then(function(){
console.log('jQuery bind complete');
});
}
reader.readAsDataURL(this.files[0]);
});
$('.btn-upload-image').on('click', function (event) {
resize.croppie('result', {
type: 'canvas',
size: 'viewport'
}).then(function (img) {
alert(img)
$.ajax({
url: "cropping.php",
type: "POST",
data: {"image":img},
success: function (data) {
html = '<img src="' + img + '" />';
$("#preview-crop-image").html(html);
}
});
});
});
</script>
</body>
</html>
But the result from croppie plugin is getting as canvas i.e base64 but we want the result from croppie plugin as same as file upload so that we can access the cropped image with $_FILES, how it can be achieved please suggest us.
Croppie is using canvas.drawImage(...) to manipulate images so you can not upload the images as you upload a file using a file input field. What you can do is, submit the base64 encoded string and reconstruct(base64 decode) the image in your server.
$imageName = $uuid.".png";
// extracting the base64 encoded string from the request payload
$imageArray = explode(";", $_POST['imagebase64']);
$imageContents = explode(",", $imageArray[1]);
$imagebase64 = base64_decode($imageContents[1]);
// saving the image to a temp file
$tempPath = sys_get_temp_dir()."/".$imageName;
file_put_contents($tempPath, $imagebase64);
Now you have the uploaded image saved in $tempPath

Progress bar for the form

I'm trying to create a progress bar for my form but it still doesn't work. After loading the form, I would like my progress bar to move from 0 percent to 100 and finish loading. I still can't see why my progress bar is not working.
My code looks like this
<form method="POST" enctype="multipart/form-data" name="newProductForm" id="newProductForm">
<input type="file" name="img" class="custom-input-file" accept=".jpg, .jpeg" required id="id_img">
<input type="text" name="category" class="form-control form-control-emphasized" id="category" placeholder="Wpisz kategorie..." maxlength="200" required>
<div class="progress">
<div id="progressBar" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
0%
</div>
</div>
<button type="button" onClick="submitFunction();" class="btn btn-block btn-primary" id="buttonSubmitProduct">
<span style="display:block;" id="buttonText">
Submit
</span>
<span style="display:none;" id="buttonSipner">
Loading......
</span>
</button>
</form>
My AJAX and JS:
<script>
function submitFunction() {
document.getElementById('buttonSubmitProduct').disabled = true;
document.getElementById('buttonText').style.display = 'none';
document.getElementById('buttonSipner').style.display = 'block';
document.getElementById('newProductForm').submit();
}
$(document).ready(function() {
$('newProductForm').on('submit', function(event) {
event.preventDefault();
var formData = new FormData($('newProductForm')[0]);
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
console.log('Bytes Loaded: ' + e.loaded);
console.log('Total Size: ' + e.total);
console.log('Percentage Uploaded: ' + (e.loaded / e.total))
var percent = Math.round((e.loaded / e.total) * 100);
$('#progressBar').attr('aria-valuenow', percent).css('width', percent + '%').text(percent + '%');
}
});
return xhr;
},
type: 'POST',
url: '',
data: formData,
processData: false,
contentType: false,
success: function() {
location.replace("/?okey=smile");
}
});
});
});
</script>
I don't see any errors in the console. Why is my code not working?
What about use the progress HTML5 tag to do that?
//calling the function in window.onload to make sure the HTML is loaded
window.onload = function() {
var pos = 0;
var t = setInterval(move, 75);
function move() {
if(pos >= 400) {
clearInterval(t);
}
else {
pos += 4;
bar.value = pos/4;
}
}
};
#container {
width: 400px;
height: 50px;
position: relative;
}
#bar {
width: 400px;
height: 50px;
position: absolute;
}
progress {
text-align: center;
}
progress:after {
content: attr(value)'%';
}
progress:before {
content: 'progress ';
}
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<div id="container">
<progress id="bar" value="0" max="100"></progress>
</div>
</body>
</html>

Handle AJAX request on the Same Page – PHP

I'm trying to create an image cropping tool, it should upload a pic, crop it and print it on the page as a image.jpg not as a base 64 (data:image)
As I know it cannot be done through HTML and javascript.
So I was trying to do this through PHP. I'm uploading and croping the image but I can't catch the result, upload it to the server and print it on the page as a image.jpg
Here is my code, please help
<div id="upload-demo"></div>
<div class="col-md-4" style="padding:5%;">
<strong>Select image to crop:</strong>
<input type="file" id="image">
<button class="btn btn-success btn-block btn-upload-image" style="margin-top:2%">Upload Image</button>
</div>
<script type="text/javascript">
var resize = $('#upload-demo').croppie({
enableExif: true,
enableOrientation: true,
viewport: { // Default { width: 100, height: 100, type: 'square' }
width: 200,
height: 200,
type: 'circle' //square
},
boundary: {
width: 300,
height: 300
}
});
$('#image').on('change', function () {
var reader = new FileReader();
reader.onload = function (e) {
resize.croppie('bind',{
url: e.target.result
}).then(function(){
console.log('jQuery bind complete');
});
}
reader.readAsDataURL(this.files[0]);
});
$('.btn-upload-image').on('click', function (ev) {
resize.croppie('result', {
type: 'canvas',
size: 'viewport'
}).then(function (img) {
$.ajax({
type: "POST",
data: {form_submit: 1,"image":img},
success: function (data) {
html = '<img src="' + img + '" />';
$("#preview-crop-image").html(html);
}
});
});
});
</script>
<?php
if(isset($_POST['form_submit'])) {
$imageProcess = 0;
if(is_array($_FILES)) {
$fileName = $_FILES['image']['tmp_name'];
$sourceProperties = getimagesize($fileName);
$resizeFileName = time();
$uploadPath = "./uploads/";
$fileExt = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
$uploadImageType = $sourceProperties[2];
$sourceImageWidth = $sourceProperties[0];
$sourceImageHeight = $sourceProperties[1];
move_uploaded_file($fileName, $uploadPath. $resizeFileName. ".". $fileExt);
$imageProcess = 1;
}
if($imageProcess == 1){
?>
<img src="<?php echo $uploadPath.$resizeFileName.'.'. $fileExt; ?>" width="700" height="700" >
<h4><b>Thump Image</b></h4>
<?php
}else{
?>
<div class="alert icon-alert with-arrow alert-danger form-alter" role="alert">
<i class="fa fa-fw fa-times-circle"></i>
<strong> Note !</strong> <span class="warning-message">Invalid Image </span>
</div>
<?php
}
$imageProcess = 0;
}
?>
<div id="upload-demo"></div>
<div class="col-md-4" style="padding:5%;">
<strong>Select image to crop:</strong>
<input type="file" id="image">
<button class="btn btn-success btn-block btn-upload-image" style="margin-top:2%">Upload Image</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.3/croppie.js" type="text/javascript"></script>
<script type="text/javascript">
var resize = $('#upload-demo').croppie({
enableExif: true,
enableOrientation: true,
viewport: { // Default { width: 100, height: 100, type: 'square' }
width: 200,
height: 200,
type: 'circle' //square
},
boundary: {
width: 300,
height: 300
}
});
$('#image').on('change', function () {
var reader = new FileReader();
reader.onload = function (e) {
resize.croppie('bind',{
url: e.target.result
}).then(function(){
console.log('jQuery bind complete');
});
}
reader.readAsDataURL(this.files[0]);
});
$('.btn-upload-image').on('click', function (ev) {
alert(111);
resize.croppie('result', {
type: 'canvas',
size: 'viewport'
}).then(function (img) {
$.ajax({
type: "POST",
data: {form_submit: 1,"image":img},
success: function (data) {
html = '<img src="' + img + '" />';
$("#preview-crop-image").html(html);
}
});
});
});
</script>
<?php
if(isset($_POST['form_submit'])) {
$imageProcess = 0;
if(is_array($_FILES)) {
$fileName = $_FILES['image']['tmp_name'];
$sourceProperties = getimagesize($fileName);
$resizeFileName = time();
$uploadPath = "./uploads/";
$fileExt = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
$uploadImageType = $sourceProperties[2];
$sourceImageWidth = $sourceProperties[0];
$sourceImageHeight = $sourceProperties[1];
move_uploaded_file($fileName, $uploadPath. $resizeFileName. ".". $fileExt);
$imageProcess = 1;
}
if($imageProcess == 1){
?>
<img src="<?php echo $uploadPath.$resizeFileName.'.'. $fileExt; ?>" width="700" height="700" >
<h4><b>Thump Image</b></h4>
<?php
}else{
?>
<div class="alert icon-alert with-arrow alert-danger form-alter" role="alert">
<i class="fa fa-fw fa-times-circle"></i>
<strong> Note !</strong> <span class="warning-message">Invalid Image </span>
</div>
<?php
}
$imageProcess = 0;
}
?>
try this it should work

Javascript state change reverting

I have a simple jQuery app to display images from Giphy based on an ajax call, and toggle animate/stop them on mouseclick by toggling the src URL and data-state attributes.
I'm also displaying a different set of images based on user input.
I have a bug where it only animates gifs displayed after the first ajax call. It doesn't animate gifs displayed by subsequent calls. console-logging for each condition makes me think that for the latter it changes the state and changes it back, but I can't wrap my head around why.
Screencap: https://screencast.com/t/uZCzH6E6hZ8n
$('document').ready(function () {
//array with topics
var topics = [
"Ronaldinho",
"Zidan",
"Messi",
"Maradona",
"Pele"
]
//function loop to display all topics in buttons
function displayTopics() {
for (var i = 0; i < topics.length; i++) {
$('#buttons').append('<div class="btn btn-info get-giphy" data-attribute=' + topics[i] +
'>' + topics[i] +
'</div>');
}
}
//call function to display all the topic buttons
displayTopics();
//on clicking button
$('#buttons').on('click', '.get-giphy', function () {
$('#gifs-appear-here').empty();
//set topic to the clicked button's data-attribute
var topic = $(this).attr('data-attribute');
//set query URL to picked topic
var queryURL = "https://api.giphy.com/v1/gifs/search?q=" + topic +
"&api_key=O2X0wRMnWEjylyUypx1F5UVxCz5Jp8kr&limit=10";
//ajax call to Giphy API
$.ajax({
url: queryURL,
method: 'GET'
}).then(function (response) {
console.log(response);
// Storing an array of results in the results variable
var results = response.data;
// Looping over every result item
for (var i = 0; i < results.length; i++) {
// Only taking action if the photo has an appropriate rating
if (results[i].rating !== "r") {
// Creating a div with the class "item"
var gifDiv = $("<div class='item'>");
// Storing the result item's rating
var rating = results[i].rating;
// Creating a paragraph tag with the result item's rating
var p = $("<p>").text("Rating: " + rating);
// Creating an image tag
var topicImage = $("<img>");
// Giving the image tag necessary attributes
topicImage.attr({
"class": "topicImage",
"src": results[i].images.fixed_height_still.url,
"data-state": "still",
"data-still": results[i].images.fixed_height_still.url,
"data-animate": results[i].images.fixed_height.url
});
// Appending the paragraph and personImage we created to the "gifDiv" div we created
gifDiv.append(topicImage);
gifDiv.append(p);
// Prepending the gifDiv to the "#gifs-appear-here" div in the HTML
$("#gifs-appear-here").prepend(gifDiv);
}
}
});
$('#gifs-appear-here').on('click', '.topicImage', function () {
var state = $(this).attr("data-state");
if (state === "still") {
$(this).attr("src", $(this).attr("data-animate"));
$(this).attr("data-state", "animate");
console.log('still --> animate');
} else if (state === "animate") {
$(this).attr("src", $(this).attr("data-still"));
$(this).attr("data-state", "still");
console.log('animate --> still');
}
else {
return false;
}
});
});
//add buttons
$('button[type="submit"]').click(function () {
var inputValue = $('.form-control').val().trim();
//don't add buttons if they're already in topics array
if (topics.includes(inputValue)) {
$('.modal').modal('show');
$('.modal-body').html('You already have a button for <b>' + inputValue +
'</b>. Use it or add something else');
setTimeout(function () {
$('.modal').modal('hide');
}, 4000);
//add buttons if they aren't in the topics array
} else {
topics.push(inputValue);
$('#buttons').empty();
displayTopics();
}
});
//get form input on pressing "enter key"
$('.form-control').keypress(function (e) {
if (e.which == 13) { //Enter key pressed
$('button[type="submit"]').click(); //Trigger search button click event
}
});
});
.row {
margin-top: 30px;
}
.col {
background-color: #eee;
padding: 15px;
border-radius: 10px;
}
.get-giphy {
margin: 0 15px 15px 0;
}
.topicImage {
max-width: 100%;
}
#media all and (min-width: 768px) {
#buttons {
border-right: 15px solid #fff;
}
#formWrap {
border-left: 15px solid #fff;
}
}
#media all and (max-width: 768px) {
#buttons {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
#formWrap {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
#media all and (max-width: 575px) {
.row {
margin-left: 0;
margin-right: 0;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
<script src="main.js"></script>
<title>Homework 6</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col col-12">
<h1>Who's your favorite Futbol star?</h1>
</div>
</div>
<div class="row">
<div id="buttons" class="col col-12 col-md-6 col-lg-6">Click a button!
<br>
<br>
</div>
<div id="formWrap" class="col col-12 col-md-6 col-lg-6">
<div class="form-group">
<input type="text" class="form-control" placeholder="You can also add more buttons!">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
<div class="row">
<div id="gifs-appear-here" class="col col-12">
Your gifs will appear here
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="answerModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Not so fast!</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
</div>
</div>
</div>
</div>
<script type="text/javascript">
</script>
</body>
</html>
As it stands, ('#gifs-appear-here').on('click', '.topicImage', ...) is executed inside the buttons' onclick handler, causing that delegated click handler to accumulate every time one of the buttons is clicked.
To fix, simply move ('#gifs-appear-here').on('click', '.topicImage', ...) out of the buttons' onclick handler.
Here it is (significantly tidied) :
$('document').ready(function () {
var topics = [
"Ronaldinho",
"Zidan",
"Messi",
"Maradona",
"Pele"
];
function displayTopics() {
for (var i = 0; i < topics.length; i++) {
$('#buttons').append('<div class="btn btn-info get-giphy" data-attribute=' + topics[i] + '>' + topics[i] + '</div>');
}
}
displayTopics();
$('#buttons').on('click', '.get-giphy', function () {
$('#gifs-appear-here').empty();
var queryURL = "https://api.giphy.com/v1/gifs/search?q=" + $(this).data('attribute') + "&api_key=O2X0wRMnWEjylyUypx1F5UVxCz5Jp8kr&limit=10";
$.ajax({
'url': queryURL,
'method': 'GET'
}).then(function (response) {
var results = response.data;
for (var i = 0; i < results.length; i++) {
if (results[i].rating !== "r") {
var gifDiv = $("<div class='item'/>").prependTo("#gifs-appear-here");
$("<img class='topicImage'/>").attr({
'src': results[i].images.fixed_height_still.url
}).data({
'state': 'still',
'images': results[i].images
}).appendTo(gifDiv);
$('<p/>').text("Rating: " + results[i].rating).appendTo(gifDiv);
}
}
});
});
$('#gifs-appear-here').on('click', '.topicImage', function () {
var data = $(this).data();
if (data.state === 'still') {
$(this).attr('src', data.images.fixed_height.url);
data.state = 'animate';
} else {
$(this).attr('src', data.images.fixed_height_still.url);
data.state = 'still';
}
});
//add buttons
$('button[type="submit"]').click(function () {
var inputValue = $('.form-control').val().trim();
//don't add buttons if they're already in topics array
if (topics.includes(inputValue)) {
$('.modal').modal('show');
$('.modal-body').html('You already have a button for <b>' + inputValue + '</b>. Use it or add something else');
setTimeout(function () {
$('.modal').modal('hide');
}, 4000);
//add buttons if they aren't in the topics array
} else {
topics.push(inputValue);
$('#buttons').empty();
displayTopics();
}
});
//get form input on pressing "enter key"
$('.form-control').keypress(function (e) {
if (e.which == 13) { //Enter key pressed
$('button[type="submit"]').click(); //Trigger search button click event
}
});
});
.row {
margin-top: 30px;
}
.col {
background-color: #eee;
padding: 15px;
border-radius: 10px;
}
.get-giphy {
margin: 0 15px 15px 0;
}
.topicImage {
max-width: 100%;
}
#media all and (min-width: 768px) {
#buttons {
border-right: 15px solid #fff;
}
#formWrap {
border-left: 15px solid #fff;
}
}
#media all and (max-width: 768px) {
#buttons {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
#formWrap {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
#media all and (max-width: 575px) {
.row {
margin-left: 0;
margin-right: 0;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
<script src="main.js"></script>
<title>Homework 6</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col col-12">
<h1>Who's your favorite Futbol star?</h1>
</div>
</div>
<div class="row">
<div id="buttons" class="col col-12 col-md-6 col-lg-6">Click a button!
<br>
<br>
</div>
<div id="formWrap" class="col col-12 col-md-6 col-lg-6">
<div class="form-group">
<input type="text" class="form-control" placeholder="You can also add more buttons!">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
<div class="row">
<div id="gifs-appear-here" class="col col-12">
Your gifs will appear here
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="answerModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Not so fast!</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
</div>
</div>
</div>
</div>
<script type="text/javascript">
</script>
</body>
</html>

Categories