Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Помощь друга #10

Merged
merged 11 commits into from
Dec 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="nouislider/nouislider.css">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<title>Кекстаграм</title>
</head>
Expand Down Expand Up @@ -45,9 +46,9 @@ <h2 class="img-upload__title visually-hidden">Загрузка фотограф

<!-- Изменение размера изображения -->
<fieldset class="img-upload__scale scale">
<button type="button" class="scale__control scale__control--smaller">Уменьшить</button>
<input type="text" class="scale__control scale__control--value" value="55%" title="Image Scale" name="scale" readonly>
<button type="button" class="scale__control scale__control--bigger">Увеличить</button>
<button type="button" class="scale__control scale__control--smaller" data-value="-1">Уменьшить</button>
<input type="text" class="scale__control scale__control--value" value="100%" title="Image Scale" name="scale" readonly>
<button type="button" class="scale__control scale__control--bigger" data-value="1">Увеличить</button>
</fieldset>

<!-- Предварительный просмотр изображения -->
Expand Down Expand Up @@ -231,12 +232,8 @@ <h2 class="success__title">Изображение успешно загруже
<div class="img-upload__message img-upload__message--loading">Загружаем...</div>
</template>
<script type="text/javascript" src="js/functions.js"></script>
<script src="nouislider/nouislider.js"></script>
<script src="pristine/Pristine-master/dist/pristine.min.js"></script>
<script type="module" src="js/fullsize-images-render.js"></script>
<script type="module" src="js/util.js"></script>
<script type="module" src="js/main.js"></script>
<script type="module" src="js/thumbnails.js"></script>
<script type="module" src="js/data.js"></script>
<script type="module" src="js/form.js"></script>
</body>
</html>
20 changes: 16 additions & 4 deletions js/form.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import {isEscapeKey, isRightString} from './util.js';
import{renderScaleButtons, destroyScaleButtons} from './image-scale.js';
import{createEffectSlider, onEffectsFilterChange, resetFilters} from './image-effects.js';

const MAX_HASHTAG_LENGTH = 20;
const MAX_COMMENT_LENGTH = 140;
const MAX_HASHTAG_COUNT = 5;
const VALID_IMAGE_TYPES = ['image/gif', 'image/jpeg', 'image/png'];
const HASHTAG_RULE = /^#[А-яа-яA-za-zёЁ]{1,19}$/;
const ErrorMessage = {
BAD_HASHTAG: 'Уникальные хештеги, каждый не более 20 символов, должны быть разделены пробелом',
BAD_COMMENT: 'Комментарий не более 140 символов'
};

const uploadButton = document.querySelector('#upload-file');
const form = document.querySelector('.img-upload__form');
const overlay = document.querySelector('.img-upload__overlay');
const cancelButton = document.querySelector('#upload-cancel');
const hashtags = document.querySelector('.text__hashtags');
const comments = document.querySelector('.text__description');
const rightHashtag = /^#[А-яа-яA-za-zёЁ]{1,19}$/;
const effectsFilter = document.querySelector('.img-upload__effects');


const isCorrectComment = (comment) => isRightString(comment, MAX_COMMENT_LENGTH);
Expand All @@ -20,7 +27,7 @@ const isCorrectHashtags = () =>{
let isСorrectTag = true;
const hashtagsArray = hashtags.value.split(' ').map((hashtag) => {
hashtag = hashtag.toLowerCase();
if(!rightHashtag.test(hashtag) || String(hashtag).length > MAX_HASHTAG_LENGTH){
if(!HASHTAG_RULE.test(hashtag) || String(hashtag).length > MAX_HASHTAG_LENGTH){
isСorrectTag = false;
}
return hashtag;
Expand Down Expand Up @@ -58,6 +65,8 @@ function closeOverlay () {
comments.removeEventListener('keydown', onFocusPreventClose);
hashtags.removeEventListener('keydown', onFocusPreventClose);
document.removeEventListener('keydown', onEscapeKeydown);
destroyScaleButtons();
resetFilters();
form.reset();
}

Expand All @@ -69,8 +78,8 @@ const validateForm = () => {
errorTextClass: 'img-upload__field-wrapper__error'
});
pristine.addValidator(hashtags, isCorrectHashtags,
'Уникальные хештеги, каждый не более 20 символов, должны быть разделены пробелом');
pristine.addValidator(comments, isCorrectComment, 'Комментарий не более 140 символов');
ErrorMessage.BAD_HASHTAG);
pristine.addValidator(comments, isCorrectComment, ErrorMessage.BAD_COMMENT);

return pristine.validate();
};
Expand All @@ -79,6 +88,8 @@ const onUploadButtonChange = () => {
if(!isPicture()) {return;}
overlay.classList.remove('hidden');
document.body.classList.add('modal-open');
renderScaleButtons();
effectsFilter.addEventListener('change', onEffectsFilterChange);
cancelButton.addEventListener('click', onCancelButtonClick);
document.addEventListener('keydown', onEscapeKeydown);
comments.addEventListener('keydown', onFocusPreventClose);
Expand All @@ -87,6 +98,7 @@ const onUploadButtonChange = () => {

export const renderUploadForm = () => {
uploadButton.addEventListener('change', onUploadButtonChange);
createEffectSlider();
form.addEventListener('submit', (evt) => {
if(!validateForm()){
evt.preventDefault();
Expand Down
71 changes: 71 additions & 0 deletions js/image-effects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const Effect = {
NONE: { name: 'none', filter: '', unit: '',
options: {range: {min: 0, max: 100}, step: 1, start: 100},
},
CHROME: {name: 'chrome', filter: 'grayscale', unit: '%',
options: { range: {min: 0, max: 100}, step: 1, start: 100},
},
SEPIA: { name: 'sepia', filter: 'sepia', unit: '%',
options: { range: {min: 0, max: 100}, step: 1, start: 100},
},
MARVIN: { name: 'marvin', filter: 'invert', unit: '%',
options: {range: {min: 0, max: 100}, step: 1, start: 100},
},
PHOBOS: {name: 'phobos', filter: 'blur', unit: 'px',
options: {range: {min: 1, max: 10}, step: 0.1, start: 10},
},
HEAT: {name: 'heat', filter: 'brightness', unit: '',
options: {range: {min: 1, max: 4}, step: 0.1, start: 4},
}
};
const DefaultSliderParam = {
range: {min: 0, max: 100}, start: 100, step: 0.1
};
Comment on lines +21 to +23

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DefaultSliderParam = {
RANGE: {min: 0, max: 100}, START: 100, STEP: 0.1
};

Copy link
Contributor Author

@PavelUd PavelUd Dec 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

к сожалению, noUiSlider не поддерживает критерии html академии


const DEFAULT_FILTER = 'NONE';
const image = document.querySelector('.img-upload__preview').querySelector('img');
const sliderValue = document.querySelector('.effect-level__value');
const sliderWrapper = document.querySelector('.img-upload__effect-level');
const slider = document.querySelector('.effect-level__slider');


export const createEffectSlider = () =>{
sliderWrapper.classList.add('hidden');
noUiSlider.create(slider, DefaultSliderParam);
};

export const resetFilters = () => {
image.style.filter = Effect[DEFAULT_FILTER].name;
sliderWrapper.classList.add('hidden');
};

const updateImagePreview = (effect) => {
image.removeAttribute('class');
image.classList.add(`effects__preview--${effect}`);

slider.noUiSlider.updateOptions(Effect[effect].options);
slider.noUiSlider.on('update', () => {
sliderValue.value = slider.noUiSlider.get();
image.style.filter = `${Effect[effect].filter}(${sliderValue.value}${Effect[effect].unit})`;
});
};

const updateSliderOptions = (effect) => {
slider.noUiSlider.updateOptions(Effect[effect].options);
};

const showFilterPreview = (effect) => {
sliderWrapper.classList.remove('hidden');
updateImagePreview(effect);
updateSliderOptions(effect);
};

export const onEffectsFilterChange = (evt) => {
const effect = evt.target.value.toUpperCase();

if (effect === Effect[DEFAULT_FILTER].name.toUpperCase()) {
resetFilters();
} else {
showFilterPreview(effect);
}
};
40 changes: 40 additions & 0 deletions js/image-scale.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const STEP = 25;
const DEFEALT_SCALE = 'scale(1)';
const MAX_PERCENT = 100;
const ScaleInterval = {
MIN: 25,
MAX: 100,
};

const scaleSmaller = document.querySelector('.scale__control--smaller');
const scaleBigger = document.querySelector('.scale__control--bigger');
const scaleValue = document.querySelector('.scale__control--value');
const image = document.querySelector('.img-upload__preview').querySelector('img');

const isValueInScaleInterval = (value) =>
value >= ScaleInterval.MIN && value <= ScaleInterval.MAX;

const updateScale = (evt) => {
const val = +scaleValue.value.replace('%', '') + STEP * +evt.target.dataset.value;
if(isValueInScaleInterval(val)){
image.style.transform = `scale(${val / MAX_PERCENT})`;
scaleValue.value = `${val}%`;
}
};

const onScaleBiggerClick = (evt) => updateScale(evt.target.dataset.value);;

Check failure on line 25 in js/image-scale.js

View workflow job for this annotation

GitHub Actions / Check

Unnecessary semicolon

const onScaleSmallerClick =(evt) => updateScale(evt.target.dataset.value);;

Check failure on line 27 in js/image-scale.js

View workflow job for this annotation

GitHub Actions / Check

Unnecessary semicolon


export const renderScaleButtons = () => {
scaleBigger.addEventListener('click', onScaleBiggerClick);
scaleSmaller.addEventListener('click', onScaleSmallerClick);
};

export const destroyScaleButtons = () => {
image.style.transform = DEFEALT_SCALE;
scaleBigger.removeEventListener('click', onScaleBiggerClick);
scaleSmaller.removeEventListener('click', onScaleSmallerClick);
};

Loading
Loading