Just started a 'Writing JS for the Web' course with following exercise and code, but getting 'unexpected end of JSON input' message upon completion of the exercise. Any idea what's going wrong? I'm coding in the following Codepen: https://codepen.io/nicolaspatschkowski/pen/GRJBZjy?editors=1111
// Get form elements
const titleInput = document.getElementById('title');
const contentInput = document.getElementById('content');
const submitButton = document.getElementById('submit-button');
const url = 'https://us-central1-open-classrooms-js-for-the-web.cloudfunctions.net/widgets';
// Get DOM elements for showing response
const responseMessage = document.getElementById('response-message');
const responseTitle = document.getElementById('response-title');
const responseId = document.getElementById('response-id');
const responseContent = document.getElementById('response-content');
submitButton.addEventListener('click', ($event) => {
$event.preventDefault();
const post = {
title: titleInput.value,
content: contentInput.value
};
submitFormData(post);
});
function makeRequest(data) {
return new Promise((resolve, reject) => {
let request = new XMLHttpRequest();
request.open('POST', url + '/create-post');
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status === 201) {
resolve(JSON.parse(request.response));
} else {
reject(JSON.parse(request.response));
}
}
};
request.setRequestHeader('Content-Type', 'application/json');
request.send(JSON.stringify(data));
});
}
async function submitFormData(post) {
try {
const requestPromise = makeRequest(post);
const response = await requestPromise;
responseMessage.textContent = response.message;
responseTitle.textContent = response.post.title;
responseId.textContent = response.post.id;
responseContent.textContent = response.post.content;
} catch (errorResponse) { responseMessage.textContent = errorResponse.error;
}
};
Related
I am trying to create a middleware that receive a form-data and return the fieldname, contentType and the value. So when I send the firts post the data view in the terminal but if I send the same request again doesn't show me the data in the terminal.
And if a toggle the image, the data come show in the terminal
This is my code:
server:
const express = require("express");
const Upes = require("../upes");
const app = express();
const start = new Upes();
app.post("/", start.setup.bind(start), (req, res) => {
res.send("all right");
});
app.listen(3000, () => {
console.log("The server is active");
});
the index of my middleware:
const getData = require("./utils/getData");
const parseContentType = require("./utils/parseContentType");
class Upes {
setup(req, res, next) {
const contentType = parseContentType(req.headers["content-type"]);
if (!contentType) {
throw new Error("Malformed content-type");
}
const SUBTYPES = ["form-data", "x-www-form-urlencoded"];
if (!SUBTYPES.includes(contentType.subtype)) {
throw new Error(
"The subtypes does not match the following subtypes: " + SUBTYPES
);
}
getData(req, contentType.params.boundary, (data) => {
console.log(data);
});
next();
}
}
module.exports = Upes;
The function that receive the data and processes it:
function getData(req, boundary, callback) {
let chunk = "";
let data = [];
req.on("data", (buffer) => {
chunk += buffer.toString();
});
req.on("end", () => {
// Split the chunk in blocks
const blocks = getBlock(chunk, boundary);
blocks.forEach((block) => {
let [params, value] = block.split("\r\n\r\n");
params = params.split(";");
let fieldname = params[1].split("=")[1].replaceAll('"', "");
let contentType = () => {
const condition = params.length === 3;
if (condition) {
let type = params[2].split(":")[1].replace(" ", "");
return type;
}
return "text-plain";
};
const payload = {
fieldname: fieldname,
contentType: contentType(),
value: "", // value.replace("\r\n", "")
};
data.push(payload);
});
callback(data);
});
}
function getBlock(body, boundary) {
boundary = boundary.replaceAll("-", "");
return body.replaceAll("-", "").split(`${boundary}`).slice(1, -1);
}
module.exports = getData;
Send the same request 20 times
I don't know what happend, please can someone help me?
I am using ckeditor in my net.core project. While saving the datatable, the image I added does not appear, it is registered to the database as
<figure class="image"><img></figure>
and src= does not appear as in lowermost the image. My adapter function is as follows
class MyUploadAdapter
{
constructor(loader) {
// The file loader instance to use during the upload.
this.loader = loader;
this.urls = '/tr/UnitType/DocUploadImage';
}
// Starts the upload process.
upload() {
return this.loader.file.then(file => new Promise((resolve, reject) => {
this._initRequest();
this._initListeners(resolve, reject, file);
this._sendRequest(file);
}));
}
// Aborts the upload process.
abort() {
if (this.xhr) {
this.xhr.abort();
}
}
_initRequest() {
const xhr = this.xhr = new XMLHttpRequest();
xhr.open('POST', this.urls, true);
xhr.responseType = 'json';
}
// Initializes XMLHttpRequest listeners.
_initListeners(resolve, reject, file) {
const xhr = this.xhr;
const loader = this.loader;
const genericErrorText = `Couldn't upload file: ${file.name}.`;
xhr.addEventListener('error', () => reject(genericErrorText));
xhr.addEventListener('abort', () => reject());
xhr.addEventListener('load', () => {
const response = xhr.response;
if (!response || response.error) {
return reject(response && response.error ? response.error.message : genericErrorText);
}
resolve({
default: response.urls
});
});
if (xhr.upload) {
xhr.upload.addEventListener('progress', evt => {
if (evt.lengthComputable) {
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
}
});
}
}
// Prepares the data and sends the request.
_sendRequest(file) {
// Prepare the form data.
const data = new FormData();
data.append('upload', file);
this.xhr.send(data);
}
}
function MyCustomUploadAdapterPlugin(editor) {
editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
return new MyUploadAdapter(loader);
};
}
I want to export this.urly to src. How is it given correctly? Is it possible in this way, if not how should I do it please help
DecoupledEditor
.create(document.querySelector('#p_Ack')
,{
extraPlugins: [MyCustomUploadAdapterPlugin],
elements:
{
img: function (element) {
const img = document.querySelector("img");
img.src = this.url;
}
}
}
)
enter image description here
enter image description here
I solved the problem..
For friends who have the same problem, #KIM-DONGWON answered the solution on https://github.com/ckeditor/ckeditor5/issues/5709.
The uploader multiple files in one request so customized file uploads after getting a response using clearQueue() not working get single file only removed
core.js:3926 ERROR TypeError: Cannot read property 'abort' of
undefined
at FileUploaderCustom.push../node_modules/ng2-file-upload/file-upload/file-uploader.class.js.FileUploader.cancelItem
(file-uploader.class.js:112)
at FileItem.push../node_modules/ng2-file-upload/file-upload/file-item.class.js.FileItem.cancel
(file-item.class.js:38)
at FileUploaderCustom.push../node_modules/ng2-file-upload/file-upload/file-uploader.class.js.FileUploader.removeFromQueue
(file-uploader.class.js:85)
at FileItem.push../node_modules/ng2-file-upload/file-upload/file-item.class.js.FileItem.remove
(file-item.class.js:41)
at FileUploaderCustom.push../node_modules/ng2-file-upload/file-upload/file-uploader.class.js.FileUploader.clearQueue
(file-uploader.class.js:92)
at FileUploaderCustom.uploaderOnward.onSuccessItem (mandate-initial.component.ts:267)
at FileUploaderCustom.push../node_modules/ng2-file-upload/file-upload/file-uploader.class.js.FileUploader._onSuccessItem (file-uploader.class.js:396)
at XMLHttpRequest.xhr.onload [as __zone_symbol__ON_PROPERTYload] (fileUploader.ts:71)
at XMLHttpRequest.wrapFn (zone.js:1255)
at ZoneDelegate.invokeTask (zone.js:431)
customized file uploads .ts
export class FileUploaderCustom extends FileUploader {
constructor(
options: FileUploaderOptions
) {
super(options);
}
uploadAllFiles(): void {
// const _this = this;
const xhr = new XMLHttpRequest();
const sendable = new FormData();
const fakeItem: FileItem = null;
this.onBuildItemForm(fakeItem, sendable);
for (const item of this.queue) {
item.headers = [];
item.withCredentials = true;
item.formData = [];
item.isReady = true;
item.isUploading = true;
item.isUploaded = false;
item.isSuccess = false;
item.isCancel = false;
item.isError = false;
item.progress = 0;
item.index = void 0;
if (typeof item._file.size !== 'number') {
throw new TypeError('The file specified is no longer valid');
}
sendable.append('file', item._file, item.file.name);
}
if (this.options.additionalParameter !== undefined) {
Object.keys(this.options.additionalParameter).forEach((key) => {
sendable.append(key, this.options.additionalParameter[key]);
})
}
xhr.onerror = () => {
this.onErrorItem(fakeItem, null, xhr.status, null);
}
xhr.onabort = () => {
this.onErrorItem(fakeItem, null, xhr.status, null);
}
xhr.open('POST', this.options.url, true);
xhr.withCredentials = true;
if (this.options.headers) {
for (let _i = 0, _a = this.options.headers; _i < _a.length; _i++) {
const header = _a[_i];
xhr.setRequestHeader(header.name, header.value);
}
}
if (this.authToken) {
xhr.setRequestHeader(this.authTokenHeader, this.authToken);
}
xhr.onload = () => {
const headers = this._parseHeaders(xhr.getAllResponseHeaders());
const response = this._transformResponse(xhr.response, headers);
const gist = this._isSuccessCode(xhr.status) ? 'Success' : 'Error';
const method = '_on' + gist + 'Item';
for (const item of this.queue) {
this[method](item, response, xhr.status, headers);
}
this._onCompleteItem(this.queue[0], response, xhr.status, headers);
}
xhr.send(sendable);
}
}
responses
this.uploaderUpdate.onSuccessItem = (item, response, status, headers) => {
this.uploadResult = JSON.parse(response);
console.log(this.uploadResult)
if (this.uploadResult.rescode == "0000") {
this.uploaderUpdate.clearQueue();
this.editMyContainer = !this.editMyContainer;
this.toastyService.success(this.uploadResult.Description);
} else if (this.uploadResult.rescode == "0001") {
this.toastyService.error(this.uploadResult.ErrorDescription);
} else if (this.uploadResult.rescode == "0002") {
this.toastyService.error(this.uploadResult.ErrorDescription);
}
};
so I have a selector that contains multiple options and below that I have a paragraph the content of which would change in accordance to the selected option in the select menu. I used find method to loop through the array and return the element(which is an object) that satisfy find function. however there is a problem with find method that I could not figure out.
'use strict';
{
function fetchJSON(url, cb) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';
xhr.onload = () => {
if (xhr.status < 400) {
cb(null, xhr.response);
} else {
cb(new Error(`Network error: ${xhr.status} - ${xhr.statusText}`));
}
};
xhr.onerror = () => cb(new Error('Network request failed'));
xhr.send();
}
function createAndAppend(name, parent, options = {}) {
const elem = document.createElement(name);
parent.appendChild(elem);
Object.keys(options).forEach(key => {
const value = options[key];
if (key === 'text') {
elem.textContent = value;
} else {
elem.setAttribute(key, value);
}
});
return elem;
}
function createLI(root, sel, options = []) {
const select = document.createElement(sel);
root.appendChild(select);
select.innerHTML = options.sort().map(repo => `<option value="${repo.id}">${repo.name}</option>`).join('\n');
select.addEventListener("change", function () {
const chosenRepoId = this.value;
const selectedRepo = options.find(repo => repo.id === chosenRepoId);
document.getElementById('repoInfo').innerHTML = selectedRepo.description;
});
}
function main(url) {
fetchJSON(url, (err, data) => {
const root = document.getElementById('root');
if (err) {
createAndAppend('div', root, { text: err.message, class: 'alert-error' });
} else {
// createAndAppend('pre', root, { text: JSON.stringify(data, null, 2) });
createLI(root, 'select', data);
}
});
}
const HYF_REPOS_URL = 'https://api.github.com/orgs/HackYourFuture/repos?per_page=100';
window.onload = () => main(HYF_REPOS_URL);
}
````js
this.value returns string.
In the comparison - const selectedRepo = options.find(repo => repo.id === chosenRepoId);
you are using strict equality operator and your chosenRepoId is numeric. So, first convert the selected value to number (use + or parseInt).
const chosenRepoId = +this.value;
const selectedRepo = options.find(repo => repo.id === chosenRepoId);
I have JSON file with 3 objects:
[
{
"image": "assets/image.jpg",
"title": "Text",
"text": "Some text",
"date": "23/11/2013"
},
...
]
And 3 HTML elements:
<div class="blog-post">
<img src="" class="blog-image"/>
<h2 class="blog-title"></h2>
<p class="blog-text"></p>
<div class="blog-date"></div>
</div>
I know how to fetch datas from 1 object to 1 html element:
((() => {
const getJSON = (url, callback) => {
const xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.responseType = 'json';
xhr.onload = () => {
const status = xhr.status;
if (status === 200) {
callback(null, xhr.response);
} else {
callback(status);
}
};
xhr.send();
};
const blogTitle = document.querySelector('.blog-title');
const blogText = document.querySelector('.blog-text');
const blogDate = document.querySelector('.blog-date');
const blogImage = document.querySelector('.blog-image');
getJSON('/test-data.json', (err, data) => {
if (err != null) {
return false;
} else {
blogImage.src = data.image;
blogTitle.innerText = data.title;
blogText.innerText = data.text;
blogDate.innerText = data.date;
}
});
}))();
But how can i make loop around all objects in json file and insert datas to html elements?
So your JSON file will return an array, and we can loop through the array like this:
getJSON('./test-data.json', (err, data) => {
if (err != null) {
return false;
} else {
data.forEach(obj => {
createElements(obj);
});
}
});
That createElements is a function I wrote:
function createElements(obj) {
const mainDiv = document.createElement('div');
mainDiv.classList.add('blog-post');
const img = document.createElement('img');
img.classList.add('blog-image');
img.src = obj['image'];
const title = document.createElement('h2');
title.classList.add('blog-title');
title.innerHTML = obj['title'];
const text = document.createElement('p');
text.classList.add('blog-text');
text.innerHTML = obj['text'];
const date = document.createElement('div');
date.classList.add('blog-date');
date.innerHTML = obj['date'];
mainDiv.appendChild(img);
mainDiv.appendChild(title);
mainDiv.appendChild(text);
mainDiv.appendChild(date);
document.querySelector('body').appendChild(mainDiv);
}
Pretty verbose, but this will add a new post to the HTML body for every object in your JSON array with the correct classes. You can change the last line of the createElements function to append it to a different element than the body.