Comparing two JSON objects from input AngularJS - javascript

I'm using this example but with some modifications. I've added input methods to my app, so user can choose any json file from local pc and read it on a page then choose one more file compare it and see results on the bottom page.
But I'm getting every time error
document.getElementById(...).forEach is not a function
What am I doing wrong? Below my code.. and not working fiddle with the error:
app.controller("Main",function ($scope) {
// ===== Start FileReader =====
$scope.leftWindow = function readSingleLeftFile(e) {
var file = e.target.files[0];
if (!file) {
return;
}
var reader = new FileReader();
reader.onload = function (e) {
var leftcontent = e.target.result;
displayLeftContents(leftcontent);
};
reader.readAsText(file);
};
function displayLeftContents(leftcontent) {
$scope.leftElement = document.getElementById('left-content');
$scope.leftElement.innerHTML = leftcontent;
}
document.getElementById('left-input')
.addEventListener('change', $scope.leftWindow, false);
$scope.rightWindow = function readSingleRightFile(e) {
var file = e.target.files[0];
if (!file) {
return;
}
var reader = new FileReader();
reader.onload = function (e) {
var rightcontent = e.target.result;
displayRightContents(rightcontent)
};
reader.readAsText(file);
};
function displayRightContents(rightcontent) {
$scope.rightElement = document.getElementById('right-content');
$scope.rightElement.innerHTML = rightcontent;
}
document.getElementById('right-input')
.addEventListener('change', $scope.rightWindow, false);
// ===== End FileReader =====
$scope.results = (function(){
var leftInputIds = {};
var rightInputIds = {};
var result = [];
document.getElementById('left-input').forEach(function (el, i) {
leftInputIds[el.id] = document.getElementById('left-input')[i];
});
document.getElementById('right-input').forEach(function (el, i) {
rightInputIds[el.id] = document.getElementById('right-input')[i];
});
for (var i in rightInputIds) {
if (!leftInputIds.hasOwnProperty(i)) {
result.push(rightInputIds[i]);
}
}
return result;
}());
});
and div
<section ng-show="dnd">
<div class="content">
<div class="row">
<div class="childGrid" style="display: flex">
<div style="width: 50%">
<input type="file" id="left-input"/>
<h3>Contents of the file:</h3>
<pre id="left-content"></pre>
</div>
<div style="width: 50%">
<input type="file" id="right-input"/>
<h3>Contents of the file:</h3>
<pre id="right-content"></pre>
</div>
</div>
<div class="parentGrid">
<div id="compare">
{{results|json}}
</div>
</div>
</div>
</div>
</section>

document.getElementById() returns a single object and not an array.
forEach need an array in odrer to operate it.
forEach method is not defined for object but it is defined for array.
So,that's why you getting an error
document.getElementById(...).forEach is not a function
EDIT1 :
do like this :
var leftInput = document.getElementById('left-input')
leftInputIds[leftInput.id] = leftInput;
var rightInput = document.getElementById('right-input')
rightInputIds[rightInput.id] = rightInput;

Related

Already known weather for city should not repeat again

I'm trying my first weather api APP. Here I'm trying to achive that if the city weather is already displayed , It should give the message "You already know the weather" . and should not repeat the weather
Here is my code. Anyone Please look at my code ...
What is the mistake I have been made.
<div class="main">
<div class="container">
<div class="search_por">
<h2>Weather </h2>
<div class="validate_msg color_white"></div>
<form>
<label for=""></label>
<input type="search" class="input_text" value="">
<button type="submit" id="sub_button" class="srh_button">Search</button>
</form>
<!-- <canvas id="icon1" width="150" height="75"></canvas> -->
<div class="dat_weather">
<ul id="list_it">
</ul>
</div>
</div>
</div>
</div>
var get_text=document.querySelector("form");
get_text.addEventListener("submit",e=>{
e.preventDefault();
var input_val=document.querySelector('input').value;
const apiKey="bc4c7e7826d2178054ee88fe00737da0";
const url=`https://api.openweathermap.org/data/2.5/weather?q=${input_val}&appid=${apiKey}&units=metric`;
fetch(url,{method:'GET'})
.then(response=>response.json())
.then(data=>{console.log(data)
const{main,sys,weather,wind}=data;
//icons-end
var error_ms=document.getElementsByClassName("validate_msg")[0];
var iconcode = weather[0].icon;
console.log(iconcode);
var li=document.createElement("Li");
var weatherinfo=`<div class="nameci font_40" data-name="${data.name},${sys.country}"><span>${data.name}</span><sup>${sys.country}</sup></div>
<div class="temp_ic">
<img class="weat_icon" src="http://openweathermap.org/img/w/${iconcode}.png">
<div class="deg">${Math.floor( main.temp )}<sup>o</sup></div>
</div>
<div class="clear">
<div>${weather[0].description}</div>
</div>
`;
li.innerHTML=weatherinfo;
var ulid=document.getElementById("list_it");
ulid.appendChild(li);
var city_name=data.name;
console.log(skycons);
var listitems=document.querySelectorAll('#list_it');
const listArray=Array.from(listitems);
if(listArray.length>0)
{
var filtered_array=listArray.filter(el=>{
let content="";
if(input_val.includes(','))
{
if(input_val.split(',')[1].length>2)
{
alert("hving 2 commos");
inputval=input_val.split(',')[0];
content=el.querySelector(".nameci span").textContent.toLowerCase();
//content=el.querySelector(".nameci").innerHTML.toLowerCase();
//content=inputval.toLowerCase();
}
else
{
content=el.querySelector(".nameci").dataset.name.toLowerCase();
}
alert(filtered_array);
}
else
{
content=el.querySelector(".nameci span").textContent.toLowerCase();
}
console.log(inputval.toLowerCase());
return inputval.toLowerCase();
});
if(filtered_array.length>0)
{
console.log(filtered_array.length);
error_ms.innerHTML="You Already know the weather of this country....";
get_text.reset();
return;
}
}
})
.catch((error)=>{
error_ms.innerHTML="Please Enter a valid city Name";
});
var error_ms=document.getElementsByClassName("validate_msg")[0];
error_ms.innerHTML="";
//var get_text=document.querySelector("form");
get_text.reset();
});
My full code is here:
https://codepen.io/pavisaran/pen/wvJaqBg
Let's try keeping track of a list of displayed locations outside of the callback:
var get_text = document.querySelector("form");
// Keep Track Of Displayed Cities Here Instead
let displayed = [];
get_text.addEventListener("submit", e => {
e.preventDefault();
var input_val = document.querySelector('input').value;
const apiKey = "bc4c7e7826d2178054ee88fe00737da0";
const url = `https://api.openweathermap.org/data/2.5/weather?q=${input_val}&appid=${apiKey}&units=metric`;
fetch(url, {method: 'GET'})
.then(response => response.json())
.then(data => {
var error_ms = document.getElementsByClassName("validate_msg")[0];
const {main, sys, weather, wind, name} = data;
if (displayed.length > 0) {
// Filter Displayed Based on Current vs name from data (response)
const filtered_array = displayed.filter(el => el === name);
if (filtered_array.length > 0) {
error_ms.innerHTML = "You Already know the weather of this country....";
get_text.reset();
return Promise.resolve();
}
}
// Add City To Array of Displayed Cities
displayed.push(name);
// Do Rest of Code to Add New City
var iconcode = weather[0].icon;
var li = document.createElement("Li");
var weatherinfo = `<div class="nameci font_40" data-name="${data.name},${sys.country}"><span>${data.name}</span><sup>${sys.country}</sup></div>
<div class="temp_ic">
<img class="weat_icon" src="http://openweathermap.org/img/w/${iconcode}.png">
<div class="deg">${Math.floor(main.temp)}<sup>o</sup></div>
</div>
<div class="clear">
<div>${weather[0].description}</div>
</div>
`;
li.innerHTML = weatherinfo;
var ulid = document.getElementById("list_it");
ulid.appendChild(li);
})
.catch((error) => {
error_ms.innerHTML = "Please Enter a valid city Name";
});
var error_ms = document.getElementsByClassName("validate_msg")[0];
error_ms.innerHTML = "";
get_text.reset();
});
You have to just check for the value which is coming from api whether it's present on your list or not. you can try this.
li.innerHTML=weatherinfo;
var ulid=document.getElementById("list_it");
var isPresent = false;
var items = ulid.getElementsByTagName("li");
for (var i = 0; i < items.length; i++){
if(items[i].innerHTML == li.innerHTML){
alert("you already know the weather")
isPresent = true;
}
}
if(!isPresent){
ulid.appendChild(li);
}

How do I add a custom attribute (such as a file hash) to a dropzone?

Using Dropzone 5.2.0.
I would like to add some custom attributes to a Dropzone when I load the page (that loads an existing file).
In my JS: On document ready, I do this:
var mydropzone = new Dropzone("#my-dropzone", {
init: function () {
var existingFile = getExistingFile();
var self = this;
if (existingFile != null) {
var size = existingFile.Length;
var name = existingFile.Name;
existingDropzoneFile = { name: name, size: size, type: 'txt' };
self.emit("addedfile", existingDropzoneFile);
}
}
});
How do I add something like adding a custom attribute of "hash" and displaying it in the html? Or foo:'bar' eve?
var mydropzone = new Dropzone("#my-dropzone", {
init: function () {
var existingFile = getExistingFile();
var self = this;
if (existingFile != null) {
var size = existingFile.Length;
var name = existingFile.Name;
var hash = existingFile.Hash;
existingDropzoneFile = { name: name, size: size, type: 'txt', hash:hash, foo:'bar' };
self.emit("addedfile", existingDropzoneFile);
}
}
});
Do I create my own template and assign this value to the template?
<div class="dz-preview dz-file-preview">
<div class="dz-details">
<div class="dz-filename"><span data-dz-name></span></div>
<div class="dz-size" data-dz-size></div>
<div class="dz-hash" data-dz-hash></div>
<div class="dz-foo" data-dz-foo></div>
<img data-dz-thumbnail />
</div>
<div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
<div class="dz-success-mark"><span>✔</span></div>
<div class="dz-error-mark"><span>✘</span></div>
<div class="dz-error-message"><span data-dz-errormessage></span></div>
</div>

Creating objects from an eventsource

I'm trying to store the date and the data from an event source to an object containing the coreid and continue to push the data and date to the correct coreid object.
As of now it's storing the wifiData to both of the coreids instead of the corresponding one. How would I push the data to the right id?
<template>
<div class="container">
<h2>Probe Diagnostics</h2>
<div class="row">
<div class="col">
<line-chart id="wifiChart" ytitle="Signal Strength" label="Wifi Strength" :colors="['#b00']" :messages="{empty: 'Waiting for data'}"
:data="wifiData" height="250px" :library="{backgroundColor: '#eee'}" :download="true" :min="-20"
:max="20"></line-chart>
<column-chart :data="wifiData" ytitle="Signal Strength" height="250px"></column-chart>
</div>
<div class="col">
<line-chart :data="psSoc" ytitle="ps-soc" height="250px"></line-chart>
<line-chart :data="psVoltage" ytitle="ps-voltage" height="250px"></line-chart>
</div>
</div>
</div>
</template>
<script>
let wifiData = [];
let psSoc = [];
let psVoltage = [];
let photons = {};
export default {
data() {
return {
wifiData,
psSoc,
psVoltage,
photons,
}
},
mounted() {
this.streamData();
},
methods: {
streamData() {
// LIVE PUSH EVENTS
if (typeof (EventSource) !== "undefined") {
var eventSource = new EventSource(
"http://10.10.10.2:8020/v1/Events/?access_token=687b5aee0b82f6536b65f");
eventSource.addEventListener('open', function (e) {
console.log("Opened connection to event stream!");
}, false);
eventSource.addEventListener('error', function (e) {
console.log("Errored!");
}, false);
eventSource.addEventListener('WiFi Signal', function (e) {
var parsedData = JSON.parse(e.data);
if (parsedData.coreid in photons) {
photons[parsedData.coreid].push([parsedData.published_at, parsedData.data])
return
} else {
photons[parsedData.coreid] =[]
}
}, false);
eventSource.addEventListener('ps-soc', function (e) {
var parsedData = JSON.parse(e.data);
psSoc.push([parsedData.published_at, parsedData.data])
}, false);
eventSource.addEventListener('ps-voltage', function (e) {
var parsedData = JSON.parse(e.data);
psVoltage.push([parsedData.published_at, parsedData.data])
}, false);
}
}
}
}
</script>
Remove wifiData completely. Instead just manage the array directly inside the lookup object:
// Initialize if needed:
if(!photons[parsedData.coreid])
photons[parsedData.coreid] = [];
// Then push directly to it:
photons[parsedData.coreid].push(/*...*/);

Parse JS : Error: Tried to encode an unsaved file

This error happens when I try to upload two files simultaneously that call the same controller for submission. Here is the relevant code:
<ion-list id="licenseDetailsInReview-list4" class=" ">
<ion-item class="item-divider " id="licenseDetails-list-item-divider5">Image 1
<div ng-if="doc.status!='approved'" class="edit">
<div class="button button-clear button-small has-file button-black " type="button">
<span style="color:black" class="image1"><i class="icon ion-edit icon-accessory custom"></i></span>
<input type="file" accept="image/*;capture=camera" name="{{doctype.doctype.documentType}}" onchange="angular.element(this).scope().$parent.uplCtrl.fileChanged(this.files, this,1)">
</div>
</div>
</ion-item>
<div class="thumbimg">
<span class="imgdet1"><div ng-if ="doc.thumb1"><img src="{{doc.thumb1.url}}"></div>
<div ng-if="!doc.thumb1"><i class="icon ion-image" style="font-size: 64px; color: rgb(136, 136, 136); vertical-align: middle;"></i></div>
</div>
</ion-list>
<ion-list id="licenseDetailsInReview-list4" class=" ">
<ion-item class="item-divider " id="licenseDetails-list-item-divider5">Image 2
<div ng-if="doc.status!='approved'" class="edit">
<div class="button button-clear button-small has-file button-black edit" type="button">
<span style="color:black" class="image2"><i class="icon ion-edit icon-accessory custom"></i></span>
<input type="file" accept="image/*;capture=camera" name="{{doctype.doctype.documentType}}" onchange="angular.element(this).scope().$parent.uplCtrl.fileChanged(this.files, this,2)">
</div>
</div>
</ion-item>
<div class="thumbimg">
<span class="imgdet2"><div ng-if ="doc.thumb2"><img src="{{doc.thumb2.url}}"></div>
<div ng-if="!doc.thumb2"><i class="icon ion-image" style="font-size: 64px; color: rgb(136, 136, 136); vertical-align: middle;"></i></div>
</div>
</ion-list>
And the controller methods :
fileChanged(files, type, i) {
const self = this;
const file = files[0];
console.log(type.name, files);
window.URL = window.URL || window.webkitURL;
self['files'] = self['files'] || {};
self['files'][type.name] = {
file: file,
blob: window.URL.createObjectURL(file)
};
var typeHolder = document.querySelector('.image' + i).innerHTML = "Uploading File.." + file.name;
this.$scope.$apply();
this.submit(self.$scope.user, i)
}
And the submit method:
submit(user, i) {
console.log('user', user);
const self = this;
//var UserDocument = Parse.Object.extend('UserDocument');
this.$scope.mutex =0;
var promises = [];
for (self.$scope.doctype.documentType in this.files) {
console.log("Files", this.files)
if (this.files.hasOwnProperty(self.$scope.doctype.documentType)) {
var parseFile = new Parse.File(self.$scope.doctype.documentType + i +'.' + this.files[self.$scope.doctype.documentType].file.name.split('.').pop(), this.files[self.$scope.doctype.documentType].file);
if (!self.$scope.doc) {
var objUserDocType = new this.UserDocumentType();
console.log("reached here");
var docType = self.$scope.usd.find(o => o.documentType == self.$scope.doctype.documentType);
objUserDocType.id = docType.objectId;
this.objUserDoc.set('docType', objUserDocType);
}
// console.log("reached here too!");
this.objUserDoc.set('owner', Parse.User.current());
//objUserDoc.set('status', 'inReview');
this.objUserDoc.set('image' + i, parseFile);
self.$scope.submitted = 1;
var p = this.objUserDoc.save().....
So when I try to upload one image before the other one has been saved, I get the error:
upload.controller.js:110 error objUserDoc Error: Tried to encode an unsaved file.
at encode (http://localhost:3000/app-1db45d.js:92569:14)
at ParseObjectSubclass._getSaveJSON (http://localhost:3000/app-1db45d.js:88168:40)
at ParseObjectSubclass._getSaveParams (http://localhost:3000/app-1db45d.js:88176:24)
at task (http://localhost:3000/app-1db45d.js:89758:34)
at TaskQueue.enqueue (http://localhost:3000/app-1db45d.js:94528:10)
at Object.save (http://localhost:3000/app-1db45d.js:89768:31)
at ParsePromise.wrappedResolvedCallback (http://localhost:3000/app-1db45d.js:90767:44)
at ParsePromise.resolve (http://localhost:3000/app-1db45d.js:90705:37)
at ParsePromise.<anonymous> (http://localhost:3000/app-1db45d.js:90777:30)
at ParsePromise.wrappedResolvedCallback (http://localhost:3000/app-1db45d.js:90767:44)
What can I do to resolve this??
thanks in advance
Two key ideas are needed: (a) we must save the file, then save the referencing object, and (b) to do N file-object saves, accumulate the save promises first, then execute all of them with Promise.all().
I tried to re-arrange your code to illustrate, but with an important caveat: I don't understand the app, nor can I see the controller surrounding all this, so the code here must be checked carefully to insure that it correctly refers to the controller level objects, including $scope.
// save a parse file, then the parse object that refers to it
function saveUserDocWithFile(objUserDoc, doctype) {
var parseFile = new Parse.File(doctype.documentType + i +'.' + this.files[doctype.documentType].file.name.split('.').pop(), this.files[doctype.documentType].file);
// first save the file, then update and save containing object
this.$scope.submitted = 1;
return parseFile.save().then(function() {
objUserDoc.set('image' + i, parseFile);
return objUserDoc.save();
});
}
With that, the submit function is simpler. It just needs to create an array of promises and execute them (using Promise.all()).
submit(user, i) {
console.log('user', user);
const self = this;
//var UserDocument = Parse.Object.extend('UserDocument');
self.$scope.mutex =0;
var promises = [];
for (self.$scope.doctype.documentType in self.files) {
console.log("Files", self.files)
if (self.files.hasOwnProperty(self.$scope.doctype.documentType)) {
if (!self.$scope.doc) {
self.objUserDoc.set('docType', objUserDocType());
}
self.objUserDoc.set('owner', Parse.User.current());
var promise = saveUserDocWithFile(self.objUserDoc, self.$scope.doctype);
promises.push(promise);
}
}
return Promise.all(promises);
}
// factor out objUserDocType creation for readability
function objUserDocType() {
var objUserDocType = new this.UserDocumentType();
var docType = this.$scope.usd.find(o => o.documentType == this.$scope.doctype.documentType);
objUserDocType.id = docType.objectId;
return objUserDocType;
}

Handle callback functions in Angular 1.5 component

I am having problems with handling callback in my Angular application.
I am trying to load an image and read it to base64 - this works fine but I need to access it outside my filesSelect.onchange; function in order to parse it to my database.
I want to set get hold of e.currentTarget.result, which I want to save as my scope : this.imageVariable.
I have following component:
(function(){
angular
.module('app')
.component('addImage', {
bindings: {
fileread: '='
},
controller: function(getfirebase, $base64){
//variables
this.base64Image = [];
this.imageVariable;
var imageElement = [];
// functions
this.userInfo = getfirebase;
this.update_settings = update_settings;
// this.filesChanged = filesChanged;
function update_settings(){
this.userInfo.$save();
};
this.data = {}; //init variable
this.click = function() { //default function, to be override if browser supports input type='file'
this.data.alert = "Your browser doesn't support HTML5 input type='File'"
}
var fileSelect = document.createElement('input'); //input it's not displayed in html, I want to trigger it form other elements
fileSelect.type = 'file';
if (fileSelect.disabled) { //check if browser support input type='file' and stop execution of controller
return;
}
this.click = function() { //activate function to begin input file on click
fileSelect.click();
}
fileSelect.onchange = function() { //set callback to action after choosing file
var f = fileSelect.files[0], r = new FileReader();
console.log(f);
r.onloadend = function(e) { //callback after files finish loading
e.currentTarget.result;
}
r.readAsDataURL(f); //once defined all callbacks, begin reading the file
};
},
controllerAs: 'addImage',
template: `
<h3>Settings-pages</h3>
<card-list class="agform">
<ul>
<li>
<p>Image preview</p>
</li>
<li>
<img ng-src="{{addImage.userInfo.image}}">
</li>
<li>
<input type="text" ng-model="addImage.userInfo.name" name="fname" placheholder="Name"><br>
<input type="text" ng-model="addImage.userInfo.email" name="fname" placheholder="Email"><br>
</li>
</ul>
{{addImage.userInfo}}
</card-list>
<card-footer>
<button ng-click='addImage.click()'>click to select and get base64</button>
{{addImage.imageVariable}}
<button ng-click='addImage.update_settings()'></button>
</card-footer>
`
})
})();
It's probably simple but I have spend hours trying to understand and solve this problem.
I can't say I know angularjs ... from a javascript perspective, it'd be as simple as saving this in another variable (me seems a popular choice), then using me.imageVariable = e.currentTarget.result;
controller: function(getfirebase, $base64){
//variables
this.base64Image = [];
this.imageVariable;
var imageElement = [];
// ************** added line
var me = this;
// ... code removed for clarity
fileSelect.onchange = function() { //set callback to action after choosing file
var f = fileSelect.files[0], r = new FileReader();
console.log(f);
r.onloadend = function(e) { //callback after files finish loading
// ******* save to imageVariable here
me.imageVariable = e.currentTarget.result;
}
r.readAsDataURL(f); //once defined all callbacks, begin reading the file
};

Categories