How to refresh components - javascript

First of all, sorry if my question is too silly, I'm still new with Polymer 2.
I'm facing a little issue. I've created a custom component, where I load some dynamic data via xhr.
Everything seems to work correctly, but I've noticed that when I leave and come back to this view, the component has not changed, even if it raises all the xhr to get new data.
I'm wondering if the issue is that the data is updated, but the DOM is still the same.
Is it possible to force the system to "reload" the component each time I visit the page?
Thanks in advance.

It's a custom "tree view component".
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-if.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-repeat.html">
<link rel="import" href="../../bower_components/paper-collapse-item/paper-collapse-item.html">
<link rel="import" href="../../bower_components/vaadin-icons/vaadin-icons.html">
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../bower_components/iron-location/iron-location.html">
<link rel="import" href="../../portal_components/portal-measurement-units/portal-measurement-units.html">
<dom-module id="portal-tree-view">
<template>
<style include="iron-flex iron-flex-alignment">
<style>
:host {
display: block;
}
.icon
{
margin-right: 24px;
--iron-icon-height: 34px;
--iron-icon-width: 34px;
color: var(--disabled-text-color);
}
.icon-small
{
margin-right: 24px;
--iron-icon-height: 20px;
--iron-icon-width: 20px;
color: var(--disabled-text-color);
}
.icon-big
{
margin-right: 24px;
--iron-icon-height: 40px;
--iron-icon-width: 40px;
color: var(--disabled-text-color);
}
.alert {
color: orange;
}
.emergency {
color: red;
}
</style>
<template is="dom-if" if=[[!loading]]>
<template is="dom-repeat" items={{tree}}>
<template is="dom-if" if="[[item.deploy]]">
<paper-collapse-item icon="icons:label" header="[[item.name]]" id="collapseitem" >
<portal-tree-view assets=[[item.children]] tasks=[[tasks]] results=[[results]] network=[[network]]></portal-tree-view>
</paper-collapse-item>
</template>
<template is="dom-if" if="[[item.mp]]">
<span style= "font-size: var(--paper-font-subhead_-_font-size); margin-left: 15px;">
<iron-icon class="icon" icon="label-outline"></iron-icon>
<iron-icon class="icon-big" style="color: black; float: right; margin-top: 40px" icon="vaadin:info-circle-o" on-click="goDetail"></iron-icon>
[[item.name]] <br/>
<span style="margin-left: 96px">
<iron-icon class="icon-small" style="color: [[item.lastacq_status]]" icon="vaadin:spark-line"></iron-icon>
<span style="color: [[checkLastAcqStatus(item)]]">[[getLastAcq(item)]]</span>
</span><br/>
<span style="margin-left: 86px">
Speed: <span style="color: [[checkSpeedStatus(item)]]">[[checkSpeed(item)]] </span>
</span><br/>
<span style="margin-left: 86px">
Acceleration: <span style="color: [[checkAccStatus(item)]]">[[checkAcc(item)]]</span>
</span><br/>
<span style="margin-left: 86px">
Temperature: <span style="color: [[checkTempStatus(item)]]">[[checkTemp(item)]]</item>
</span><br/>
</span><br/>
</template>
<template is="dom-if" if="[[item.transmitter]]">
<span style= "font-size: var(--paper-font-subhead_-_font-size); margin-left: 15px;">
<iron-icon class="icon" icon="label-outline"></iron-icon>
[[item.name]]<br/>
</span>
<span style="margin-left: 96px">
<iron-icon class="icon-small" style="color: [[item.latcom_status]]" icon="settings-input-antenna"></iron-icon>
<span style="color: [[checkLastComStatus(item)]]">[[getLastCom(item)]]</span>
</span><br/>
</template>
<template is="dom-if" if="[[item.endpoint]]">
<span style= "font-size: var(--paper-font-subhead_-_font-size); margin-left: 15px;">
<iron-icon class="icon" icon="label-outline"></iron-icon>
[[item.name]]<br/>
</span>
</template>
</template>
</template>
<template is="dom-if" if=[[loading]]>
<div class="center-center layout horizontal">
<img src="portal_components/portal-tree-view/loading.gif" />
</div>
</template>
<portal-lite-global-variables id="GLOBALS"></portal-lite-global-variables>
<portal-measurement-units id="UNITS"></portal-measurement-units>
<iron-location id="location"></iron-location>
</template>
<script>
/**
* `portal-tree-view`
*
*
* #customElement
* #polymer
* #demo demo/index.html
*/
class portalTreeView extends Polymer.Element {
static get is() { return 'portal-tree-view'; }
static get properties() {
return {
assets: {
type: Array,
notify: true,
},
tasks: {
type: Object,
notify: true,
},
results: {
type: Object,
notify: true,
},
network: {
type: Array,
notify: true
},
tree: {
type: Array,
notify: true
},
trigger: {
type: Boolean,
observer: '_trigger'
}
};
}
static get observers() {
return [
'fullAssets(tasks, results)'
]
}
_trigger()
{
if (this.trigger)
{
this.ready();
console.log("trigger")
this.fullAssets();
}
}
toFixed(value, precision) {
return Number(value).toFixed(precision);
}
goDetail(event)
{
var item = event.model.item;
this.$.location.path="portal-lite-asset-details/"+item._id;
}
checkLastComStatus(item)
{
if (this.network[item.mac] !== undefined)
{
var current = this.$.GLOBALS.getUTCTimeStamp(new Date());
if (current < this.$.GLOBALS.getUTCTimeStamp(new Date(this.network[item.mac].last_com)) + 54000)
return 'orange';
else if (current > this.$.GLOBALS.getUTCTimeStamp(new Date(this.network[item.mac].last_com)) + 54000)
return 'red';
}
}
getLastAcq(item)
{
if (this.results[item._id] !== undefined)
return new Date(this.results[item._id].acqend).toLocaleDateString() + " " + new Date(this.results[item._id].acqend).toLocaleTimeString();
}
getLastCom(item)
{
if (this.network[item.mac] !== undefined)
return new Date(this.network[item.mac].last_com).toLocaleDateString() + " " + new Date(this.network[item.mac].last_com).toLocaleTimeString();
}
checkLastAcqStatus(item)
{
if (this.tasks[item._id] !== undefined)
return this.$.GLOBALS.checkTask(this.tasks[item._id], this.results[item._id]);
}
checkSpeed(item)
{
if (this.results[item._id] !== undefined)
{
if (this.results[item._id].globals.vib !== undefined &&
this.results[item._id].globals.vib.v !== undefined)
{
var aux = this.$.UNITS.speed(this.results[item._id].globals.vib.v[0]);
return aux.value.toFixed(2) + " " + aux.desc;
}
}
}
checkSpeedStatus(item)
{
if (this.results[item._id] !== undefined)
{
if (this.results[item._id].globals.vib !== undefined &&
this.results[item._id].globals.vib.v !== undefined)
{
if (this.results[item._id].globals.vib.v[1] == 1) return "orange";
else if (this.results[item._id].globals.vib.v[1] == 2) return "red";
}
}
}
checkAccStatus(item)
{
if (this.results[item._id] !== undefined)
{
if (this.results[item._id].globals.vib !== undefined &&
this.results[item._id].globals.vib.a !== undefined)
{
if (this.results[item._id].globals.vib.a[1] == 1) return "orange";
else if (this.results[item._id].globals.vib.a[1] == 2) return "red";
}
}
}
checkTempStatus(item)
{
if (this.results[item._id] !== undefined)
if (this.results[item._id].globals.temp !== undefined &&
this.results[item._id].globals.temp !== null)
{
if (this.results[item._id].globals.temp[1] == 1) return "orange";
else if (this.results[item._id].globals.temp[1] == 2) return "red";
}
}
checkAcc(item)
{
if (this.results[item._id] !== undefined)
{
if (this.results[item._id].globals.vib !== undefined &&
this.results[item._id].globals.vib.a !== undefined)
{
var aux = this.$.UNITS.g(this.results[item._id].globals.vib.a[0]);
return aux.value.toFixed(2) + " " + aux.desc;
}
}
}
checkTemp(item)
{
if (this.results[item._id] !== undefined)
{
if (this.results[item._id].globals.temp !== undefined &&
this.results[item._id].globals.temp !== null)
{
var aux = this.$.UNITS.temp(this.results[item._id].globals.temp[0]);
return aux.value.toFixed(1) + " " + aux.desc;
}
}
}
fullAssets()
{
if (this.assets !== undefined && this.network !== undefined)
{
this.loading = false;
this.assets.sort(function(d1,d2)
{
if (d1.children.length > 0) return -1;
return 1;
});
for (var i = 0; i < this.assets.length; i++)
{
this.assets[i].endpoint = false;
this.assets[i].mp = false;
this.assets[i].transmitter = false;
if (this.assets[i].children.length === 0)
this.assets[i].endpoint = true;
if (this.assets[i].t == 33554435)
{
this.assets[i].endpoint = false;
this.assets[i].transmitter = true;
this.assets[i].mac = this.assets[i].optionals.mac.toUpperCase();
}
if (this.assets[i].t == 16777218)
{
this.assets[i].endpoint = false;
this.assets[i].mp = true
}
this.assets[i].deploy = !this.assets[i].mp && !this.assets[i].endpoint && !this.assets[i].transmitter;
}
this.notifyPath('tree', this.assets);
}
}
constructor()
{
super();
this.loading = true;
this.queue_results = 0;
}
ready()
{
super.ready();
}
}
window.customElements.define(portalTreeView.is, portalTreeView);
</script>
</dom-module>
On this.$.UNITS I have a set of functions to make a conversion of values (Metric, Imperial, etc...).
The function checkSpeed(item) is executed each time I show the view.
Via console.log I can check that the value returned is always correct, but when leaving, I change the unity (from metric to imperial, for instance), and when I'm back again the view in the component remains in the old unities (even if the console.log in the function returns the correct value).
Hope it's useful.
Thanks in advance.
[EDIT]
Finally found out the solution here: https://easyusedev.wordpress.com/2015/11/06/dynamically-loading-polymer-elements-on-the-fly/
In order to be sure that the component is refresed each time I call the view, create the component manually when everything's ready to load the component:
var tree = document.createElement('portal-tree-view');
And, when leaving, I remove it:
var element = this.$.container.querySelector("portal-tree-view");
element.parentNode.removeChild(element)
En cualquier caso, muchas gracias por tu tiempo Álvaro.
Best regards.

I see you are doing this.notifyPath('tree', this.assets); in fullAssets(), but I think the syntax is not correct.
From the docs:
When calling notifyPath, you need to use the exact path that changed.
For example, calling this.notifyPath('profile') doesn't pick up a
change to profile.name because the profile object itself hasn't
changed.
So try to do this:
this.notifyPath('tree.property_you_want_to_be_changed');
Or maybe would be better to you to use MutableData mixin. This mixin allows the array to be updated and the UI be notified simpley doing
this.notifyPath('tree');

Related

Script from HTML to VUE - change bg color on click

Currently I'm able to change color of a div, that from now on I will refer to as 'Cell', in a vanilla html file as follows:
<script type=text/javascript>
var type = -1;
function colorCell() {
if(type==0){
event.target.style.backgroundColor = ' #fdcb6e ';
}else if(type==1){
event.target.style.backgroundColor = ' #fab1a0 ';
}else if(type==2){
event.target.style.backgroundColor = ' #fd79a8 ';
}else if(type==-1){
event.target.style.backgroundColor = ' azure ';
}
}
function delay(){
type=0;
}
function panne(){
type=1;
}
function reserved(){
type=2;
}
function clean(){
type=-1;
}
</script>
Cell can change to different colors according to the type parameter. Type changes when other buttons (not cells) are clicked.
Any orientation of how to get this done in VUE? I can't get it working.
EDIT:
To add information to proposed problem, I need each cell to be colored only when clicked. Cells are formed in a iterative way as follows:
<div class="body">
<div v-for="column in 25" :key="column.id" class="column">
<div v-for="row in 10" :key="row.id" class="frame">
<span v-if="column == 1">ROW-NAME</span>
<div v-else class="selector"><b-button #click="colorCell($event)" /></div>
</div>
</div>
</div>
You could achieve this with a component that looks something like this:
<template>
<div>
<div :style="{ backgroundColor }">Cell</div>
<button #click="delay">delay</button>
<button #click="panne">panne</button>
<button #click="reserved">reserved</button>
<button #click="clean">clean</button>
</div>
</template>
<script>
export default {
data() {
return {
type: -1,
}
},
computed: {
backgroundColor() {
if (this.type == 0) {
return '#fdcb6e';
} else if (this.type == 1) {
return '#fab1a0';
} else if (this.type == 2) {
return '#fd79a8';
} else if (this.type == -1) {
return 'azure';
}
return '';
}
},
methods: {
delay() {
this.type = 0;
},
panne() {
this.type = 1;
},
reserved() {
this.type = 2;
},
clean() {
this.type = -1;
}
}
}
</script>
UPDATE:
In order to colour the cells individually you could do it like this (note: you were trying to use column.id and row.id but these properties do not exist - column and row are integers):
<div class="body">
<div v-for="column in 25" :key="column" class="column">
<div v-for="row in 10" :key="row" class="frame" :ref="`${column}-${row}`">
<span v-if="column == 1">ROW-NAME</span>
<div v-else class="selector"><b-button #click="colorCell(column, row)" /></div>
</div>
</div>
</div>
colorCell(col, row) {
const el = this.$refs[`${col}-${row}`][0];
// Update the colour of the individual cell here e.g. el.style.backgroundcolor = '#fdcb6e'
}

Setting state in componentDidMount with loops and ifs

I have a provider that provides tags for news articles (list with news). If they are more than three, then the additional tags (>3) will be grouped together (called plusTags in the example code). I can see in my console that I have all the tags, but they are not distributed correctly. Ex.
On the first page I have four news with the distributed tags "a,b,c", b", "ac" "b". On the next page, the news articles are (obviously) different, but the distribution of the tags is the SAME ("a,b,c", b", "ac" "b") as on the first page, even if the tags should be different. So the distribution follows the same pattern. I suspect it's my code in my "componentDidMount" function, as its there where I distribute all the tags. Suspect it might repeat because this function repeats itself?
public componentDidMount(): void {
let tags = [];
let plusTags = [];
if (this.props.tags != null) {
if (this.props.tags.length > 0) {
for (var i = 0; i < 3; i++) {
if (this.props.tags[i] != undefined) {
tags.push(this.props.tags[i] + " ");
}
}
for (var j = this.props.tags.length - 1; j >= 3; j--) {
if (this.props.tags[i] != undefined) {
plusTags.push(this.props.tags[j] + " ");
}
}
} else {
tags = this.props.tags;
}
}
this.setState({
tags: tags,
plusTags: plusTags
});
}
and in my render
public render(): React.ReactElement<INewsTagsProps> {
return <React.Fragment>
<div className={styles.tagContainer}>
{
this.state.tags ?
this.state.tags.map((t) => {
if (this.props.background == BackgroundType.None) {
return (
<a href={this.props.tagPageUrl + "?tag="+ t}>
<span className={styles.tagNewsTiles}>{t}</span>
</a>);
}
else {
return(
<a href={this.props.tagPageUrl + "?tag="+ t}>
<span className={styles.tagFollowedNews}>{t}</span>
</a>);
}
})
: null
}
{this.state.plusTags.length > 0 ?
<span className={`callout-target-${this.state.targetIndex} ${this.props.background == BackgroundType.None ? styles.tagNewsTiles : styles.tagFollowedNews}`}
onClick={(e) => {e.stopPropagation(); this.setState({plusTagsDialogOpen: true});}}>+ {this.state.plusTags.length}</span>
:
null
}
</div>
<Callout
className="ms-CalloutExample-callout"
gapSpace={0}
target={this.state.target}
onDismiss={() => this.closeDialog()}
hidden={!this.state.plusTagsDialogOpen}
isBeakVisible={true}
beakWidth={10}
directionalHint={DirectionalHint.topCenter}
>
<div className={styles.tagPopupWrapper}>
<div className={styles.tagPopupContainer}>
{this.state.plusTags ?
this.state.plusTags.map((t) => {
if (this.props.background == BackgroundType.None) {
return (
<a href={this.props.tagPageUrl+ "?tag="+t}>
<span className={styles.tagNewsTiles}>{t}</span>
</a>);
}
else {
return(
<a href={this.props.tagPageUrl+ "?tag="+t}>
<span className={styles.tagFollowedNews}>{t}</span>
</a>);
}
}):
null}
</div>
</div>
</Callout>
;

Error during checkout with VISA card

I'm completely new nopCommerce. One of my client is getting error during check out with VISA card. He is getting the following screen. I'm not sure where do I start to troubleshoot. Can you please help me? Some how I'm not able to post exact HTML document. But please consider below code as properly formatted HTML.
<script type="text/javascript">
(function (f, b) {
if (!b.__SV) {
var a, e, i, g;
window.mixpanel = b;
b._i = [];
b.init = function (a, e, d) {
function f(b, h) {
var a = h.split(".");
2 == a.length && (b = b[a[0]], h = a[1]);
b[h] = function () {
b.push([h].concat(Array.prototype.slice.call(arguments, 0)))
}
}
var c = b;
"undefined" !== typeof d ? c = b[d] = [] : d = "mixpanel";
c.people = c.people || [];
c.toString = function (b) {
var a = "mixpanel";
"mixpanel" !== d && (a += "." + d);
b || (a += " (stub)");
return a
};
c.people.toString = function () {
return c.toString(1) + ".people (stub)"
};
i = "disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");
for (g = 0; g < i.length; g++) f(c, i[g]);
b._i.push([a, e, d])
};
b.__SV = 1.2;
a = f.createElement("script");
a.type = "text/javascript";
a.async = !0;
a.src = "//cdn.mxpnl.com/libs/mixpanel-2.2.min.js";
e = f.getElementsByTagName("script")[0];
e.parentNode.insertBefore(a, e)
}
})(document, window.mixpanel || []);
var mode = 'prd'.toLowerCase();
var token = '';
if (mode == 'demo') {
token = 'xxxxxxxxxxxxxxxxxxxxxx';
} else if (mode == 'prd' || mode == 'prda' || mode == 'prdk') {
token = 'xxxxxxxxxxxxxxxxxxxxxx';
} else if (mode == 'test') {
token = 'xxxxxxxxxxxxxxxxxxx';
} else {
token = 'xxxxxxxxxxxxxxxxxxxxxxxxx';
}
if (token != '') {
mixpanel.init(token, {
persistence: 'localStorage'
});
}
</script><!-- end Mixpanel -->
<script type="text/javascript">
if (self !== top && typeof mixpanel !== "undefined") {
mixpanel.track("inFrame", {
"merchant_id": "XXXX(actual number here)",
"tid": "XXXX(actual number here)"
});
}
</script>
<style type="text/css">
BODY, TD, INPUT, SELECT, TEXTAREA, BUTTON, .normal {
font-family: arial,helvetica,sans-serif;
font-size: 10pt;
font-weight: normal;
}
.small {
font-size: 10pt;
}
.medium {
font-size: 14pt;
}
.large {
font-size: 18pt;
}
</style>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- process-transaction-response -->
<html>
<head>
<meta http-equiv="refresh" content="1;url=http://www.myvirtualmerchant.com?
ssl_approval_code=++++++&
ssl_cvv2_response=&
ssl_exp_date=XXXX(actual number here)&
ssl_account_balance=0.00&
ssl_get_token=&
ssl_token=&
ssl_departure_date=&
ssl_token_response=&
ssl_result_message=DECLINED&
ssl_invoice_number=XXXX(actual number here)&
ssl_description=Name1+Name2&
ssl_amount=184.48&
ssl_txn_id=GUID&
ssl_result=1&
ssl_card_number=XXXX(actual number here)&
ssl_completion_date=&
ssl_txn_time=10%2F28%2F2016+04%3A03%3A18+PM&
ssl_avs_response=G">
<style type="text/css">
BODY, TD, INPUT, SELECT, TEXTAREA, BUTTON, .normal {
font-family: arial,helvetica,sans-serif;
font-size: 10pt;
font-weight: normal;
}
.small {
font-size: 10pt;
}
.medium {
font-size: 14pt;
}
.large {
font-size: 18pt;
}
</style>
</head>
<form name="frmMenu" action="#" method="POST">
<input type="hidden" name="dispatchMethod" />
<input type="hidden" name="permissionDesc" />
<input type="hidden" name="menuAction" />
<input type="hidden" name="thClientID" value="" />
</form> <!-- start Mixpanel -->
</body>
</html>

Passing array of dates to Javascript sort

I'm having problem with javascript sort function. I have this function:
var compare = function(a, b) {
if(a.last_nom < b.last_nom) {
return -1;
}
if(a.last_nom > b.last_nom) {
return 1;
}
return 0;
}
And the I call it with:
var sortedData = fullData.sort(compare);
But I don't know how to pass dates correctly.
You can find jsbin example here
Thank you in advance
As requested, to make sense of my code here is full code:
<html lang="en-US">
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.0/css/materialize.min.css">
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.0/sweetalert.min.css" rel="stylesheet">
<link rel="icon" href="http://www.mzirafos.lt/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="http://www.mzirafos.lt/favicon.ico" type="image/x-icon" />
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mėmelio Žirafos - Facebook feeds page</title>
<style>
html {
overflow-y: scroll;
}
header {
margin-bottom: 50px;
}
.progress {
top: 50%;
width: 50%;
margin: 0 auto;
}
.event-only .not-event {
display: none;
}
.post-by {
display: block;
margin-bottom: 25px;
}
.post-date {
display: block;
}
.card .card-content .card-title {
line-height: 26px;
margin-bottom: 15px;
display: inline-block;
}
img.responsive-img {
width: 100%;
}
</style>
</head>
<body>
<div class="progress">
<div class="indeterminate"></div>
</div>
<div class="hide" id="content">
<!--header-->
<header>
<nav class="top-nav">
<div class="container">
<div class="nav-wrapper">
<p>Mėmelio Žirafos Facebook feeds page</p>
</div>
</div>
</nav>
</header>
<!--end header-->
<div class="container">
<div class="row">
<!--checkbox to show all posts or events only-->
<div class="col s6">
<p>
<input type="checkbox" id="events-only" />
<label for="events-only">Show events only</label>
</p>
</div>
<!--end checkbox-->
</div>
<div class="row">
<h3 class="center-align" id="posts-acc-title">Facebook posts</h3>
<!--posts wrapper-->
<div class="col s12" id="fb-posts-wrap"></div>
<!--end posts wrapper-->
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.0/js/materialize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sugar/1.4.1/sugar.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.0/sweetalert.min.js"></script>
<script src="https://cdn.rawgit.com/zenorocha/clipboard.js/master/dist/clipboard.min.js"></script>
<script>
(function() {
/*
* Our Globals
*/
var html = '';
var finalData = [];
var token = 'CAAQYWWjo5zkBAGlqs2AxxsWKcgWEI0VM3UA7555dhCQEOCTu9VW91tpfaNvrt4tS0w8DkxPJHvRENRrMeDT9QC1aSvHdZA7nhw9ZBqZAyUhMM6PTQoJggn7pJRHEO8xQJp8lsGZAqixVU8SvrMlhUUhwmzB11h9ISqd3MvmoD4aVZBPPD1geO';
var baseURL =
'https://graph.facebook.com/v2.4/{slug}/feed?fields=picture,created_time,message,link,type,description,caption,full_picture,id,admin_creator,from&limit=50&access_token={token}';
var slugs = [{
slug: 'sisaidgallery',
complete: false
}, {
slug: 'duzenos',
complete: false
}, {
slug: 'bbcnews',
complete: false
}, {
slug: 'Klaipeda.renginiai',
complete: false
}, {
slug: 'PORTbyBarBara',
complete: false
}, {
slug: 'Kastonas',
complete: false
}, {
slug: 'klaipedosdramosteatras',
complete: false
}, {
slug: '238899589464193',
complete: false
}];
/*
* allComplete
*/
var allComplete = function() {
for (var i = 0; i < slugs.length; i++) {
if (slugs[i].complete === false) {
return false;
}
}
return true;
};
/*
* makeURL
*/
var makeURL = function(url, token, slug) {
return url.replace('{token}', token).replace('{slug}', slug);
};
/*
* Date formatter
*/
var dateFormatter = function(date) {
var dateFormat = '{HH}:{mm}, {Weekday}, {d} {Month}, {yyyy}';
return Date.create(date).format(dateFormat);
}
/*
* Mark slug as complete
*/
var completeSlug = function(mySlug) {
for (var i in slugs) {
if (slugs[i].slug === mySlug) {
slugs[i].complete = true;
}
}
};
var copyTextID = 100;
/*
* template
*/
var template = '' +
'<div class="card blue-grey darken-1 hoverable {isEvent}">' +
'<div class="card-content white-text">' +
'<span class="post-date">Posted on: {fb-post-date}</span>' +
'<span class="post-by">Post by: {fb-post-from}</span>' +
'<div class="row">' +
'<div class="col s2">' +
'<img class="responsive-img" src="{fb-image}" alt=""/>' +
'</div>' +
'<div class="col s10" id="post-target-{fb-post-id}">' +
'<span class="card-title">{fb-post-title}</span>' +
'<p>{fb-post-text}</p>' +
'</div>' +
'</div>' +
'</div>' +
'<div class="card-action">' +
'<a target="_blank" href="{fb-post-link}">Open post</a>' +
'<a class="waves-effect waves-light btn white-text red darken-1 hoverable" data-clipboard-target="#post-target-{fb-post-id}"><i class="material-icons right">subject</i>Copy</a>' +
'</div>' +
'</div>';
/*
* checking title, text and images
*/
var replaceUndefined = function(str) {
return str === undefined ? '' : str;
};
var replaceImage = function(str) {
return str === undefined ? 'https://placehold.it/350x150' : str;
};
/*
* bindTemplate
*/
var bindTemplate = function(template, obj) {
return template
.replace('{isEvent}', obj.type === 'event' ? '' : 'not-event')
.replace('{fb-image}', replaceImage(obj.picture))
.replace('{fb-post-from}', obj.from.name)
.replace('{fb-post-title}', replaceUndefined(obj.description))
.replace('{fb-post-text}', replaceUndefined(obj.message))
.replace('{fb-post-link}', obj.link)
.replace('{fb-post-date}', dateFormatter(obj.created_time))
.replace(/{fb-post-id}/g, obj.id);
};
var makeAjax = function(fbUrl, next, slug) {
$.ajax({
url: fbUrl
}).done(function(data) {
next(data, slug);
});
};
/*
* renderTemplate
*/
var renderTemplate = function() {
$('#fb-posts-wrap').html(html);
};
/*
* makeAjaxCalls
*/
var makeAjaxCalls = function(slugs) {
slugs.forEach(function(slug) {
makeAjax(makeURL(baseURL, token, slug.slug), showAllPosts, slug.slug);
});
};
/*
* Flatten data
*/
var flattenData = function(data) {
var fullData = [];
var empty = [];
data.forEach(function(row) {
fullData.push(row.data);
});
return empty.concat.apply(empty, fullData);
};
var compare = function(a, b) {
if (a.last_nom < b.last_nom) {
return -1;
}
if (a.last_nom > b.last_nom) {
return 1;
}
return 0;
}
var showAllPosts = function(data, slug) {
// Let's first mark this slug as complete
completeSlug(slug);
// And store our data
finalData.push(data);
if (allComplete()) {
// merge all data
var fullData = flattenData(finalData);
// sort all data and
var sortedData = fullData.sort(compare);
// build the html
sortedData.forEach(function(obj) {
html += bindTemplate(template, obj);
});
// call the renderTemplateFunction
renderTemplate();
// finally hide the progress bar
$('.progress').fadeOut();
$('#content').removeClass('hide');
}
};
/*
* Listen to the change in the checkbox
*/
$('#events-only').change(function() {
if ($(this).is(':checked')) {
// hide the non events with css
$('#fb-posts-wrap').addClass('event-only');
} else {
// show the non events with css
$('#fb-posts-wrap').removeClass('event-only');
}
});
/*
* Kick off
*/
makeAjaxCalls(slugs);
})();
</script>
</body>
</html>
What is last_nom? There is no such function in JS Date specification
Try this:
function compare(a, b) {
if (a.getTime() > b.getTime())
return 1;
if (a.getTime() < b.getTime())
return -1;
return 0
}
var sortedDatesArray = unsortedDatesArray.sort(compare);

Preventing HTML and Script injections in Javascript

Assume I have a page with an input box. The user types something into the input box and hits a button. The button triggers a function that picks up the value typed into the text box and outputs it onto the page beneath the text box for whatever reason.
Now this has been disturbingly difficult to find a definitive answer on or I wouldn't be asking but how would you go about outputting this string:
<script>alert("hello")</script> <h1> Hello World </h1>
So that neither the script is executed nor the HTML element is displayed?
What I'm really asking here is if there is a standard method of avoiding both HTML and Script injection in Javascript. Everyone seems to have a different way of doing it (I'm using jQuery so I know I can simply output the string to the text element rather than the html element for instance, that's not the point though).
You can encode the < and > to their HTML equivelant.
html = html.replace(/</g, "<").replace(/>/g, ">");
How to display HTML tags as plain text
myDiv.textContent = arbitraryHtmlString
as #Dan pointed out, do not use innerHTML, even in nodes you don't append to the document because deffered callbacks and scripts are always executed. You can check this https://gomakethings.com/preventing-cross-site-scripting-attacks-when-using-innerhtml-in-vanilla-javascript/ for more info.
A one-liner:
var encodedMsg = $('<div />').text(message).html();
See it work:
https://jsfiddle.net/TimothyKanski/wnt8o12j/
I use this function htmlentities($string):
$msg = "<script>alert("hello")</script> <h1> Hello World </h1>"
$msg = htmlentities($msg);
echo $msg;
From here
var string="<script>...</script>";
string=encodeURIComponent(string); // %3Cscript%3E...%3C/script%3
My solution using typescript + decorators + regex
const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
return value.replace(removeTag, "");
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
function filter(target) {
return class extends target {
constructor(...args) {
super(...args);
}
setState(opts) {
const state = {
username: this.filter(opts.username),
password: this.filter(opts.password),
};
super.setState(state);
}
filter(value) {
const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
return value.replace(removeTag, "");
}
};
}
let Form = class Form {
constructor() {
this.state = {
username: "",
password: "",
};
}
setState(opts) {
this.state = {
...this.state,
...opts,
};
}
getState() {
return this.state;
}
};
Form = __decorate([
filter,
__metadata("design:paramtypes", [])
], Form);
function getElement(key) {
return document.getElementById(key);
}
const button = getElement("btn");
const username = getElement("username");
const password = getElement("password");
const usernameOutput = getElement("username-output");
const passwordOutput = getElement("password-output");
function handleClick() {
const form = new Form();
form.setState({ username: username.value, password: password.value });
usernameOutput.innerHTML = `Username: ${form.getState().username}`;
passwordOutput.innerHTML = `Password: ${form.getState().password}`;
}
button.onclick = handleClick;
<!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.0" />
<style>
:root {
--bg: #1d1907;
--foreground: #e3e0cd;
--primary: #cfb53b;
--black: #333;
--white: #fafafa;
}
#keyframes borderColor {
from {
border-bottom: 1px solid var(--foreground);
}
to {
border-bottom: 1px solid var(--primary);
}
}
* {
outline: none;
border: none;
}
body {
padding: 0.5rem;
font-family: "Fira Code";
background-color: var(--bg);
color: var(--foreground);
}
input {
border-bottom: 1px solid var(--foreground);
background-color: var(--black);
color: var(--foreground);
padding: 0.5rem;
}
input:focus {
animation-name: borderColor;
animation-duration: 3s;
animation-fill-mode: forwards;
}
button {
padding: 0.5rem;
border-radius: 3px;
border: 1px solid var(--primary);
background-color: var(--primary);
color: var(--white);
}
button:hover,
button:active {
background-color: var(--white);
color: var(--primary);
}
.form {
margin-bottom: 2rem;
}
</style>
<title>Decorator</title>
</head>
<body>
<h1>Prevent Injection</h1>
<div class="form">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" placeholder="Type your username" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" placeholder="Type your password" />
</div>
<div class="form-group">
<button id="btn">Enviar</button>
</div>
</div>
<div class="form-result">
<p id="username-output">Username:</p>
<p id="password-output">Password:</p>
</div>
<script src="/dist/pratica1.js"></script>
</body>
</html>
Typescript Code bellow:
type State = {
username: string;
password: string;
};
function filter<T extends new (...args: any[]) => any>(target: T): T {
return class extends target {
constructor(...args: any[]) {
super(...args);
}
setState(opts: State) {
const state = {
username: this.filter(opts.username),
password: this.filter(opts.password),
};
super.setState(state);
}
filter(value: string) {
const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
return value.replace(removeTag, "");
}
};
}
#filter
class Form {
private state: State;
constructor() {
this.state = {
username: "",
password: "",
};
}
setState(opts: State) {
this.state = {
...this.state,
...opts,
};
}
getState() {
return this.state;
}
}
function getElement(key: string): HTMLElement | null {
return document.getElementById(key);
}
const button = getElement("btn") as HTMLButtonElement;
const username = getElement("username") as HTMLInputElement;
const password = getElement("password") as HTMLInputElement;
const usernameOutput = getElement("username-output") as HTMLParagraphElement;
const passwordOutput = getElement("password-output") as HTMLParagraphElement;
function handleClick() {
const form = new Form();
form.setState({ username: username.value, password: password.value });
usernameOutput.innerHTML = `Username: ${form.getState().username}`;
passwordOutput.innerHTML = `Password: ${form.getState().password}`;
}
button.onclick = handleClick;
Try this method to convert a 'string that could potentially contain html code' to 'text format':
$msg = "<div></div>";
$safe_msg = htmlspecialchars($msg, ENT_QUOTES);
echo $safe_msg;
Hope this helps!
Use this,
function restrict(elem){
var tf = _(elem);
var rx = new RegExp;
if(elem == "email"){
rx = /[ '"]/gi;
}else if(elem == "search" || elem == "comment"){
rx = /[^a-z 0-9.,?]/gi;
}else{
rx = /[^a-z0-9]/gi;
}
tf.value = tf.value.replace(rx , "" );
}
On the backend, for java , Try using StringUtils class or a custom script.
public static String HTMLEncode(String aTagFragment) {
final StringBuffer result = new StringBuffer();
final StringCharacterIterator iterator = new
StringCharacterIterator(aTagFragment);
char character = iterator.current();
while (character != StringCharacterIterator.DONE )
{
if (character == '<')
result.append("<");
else if (character == '>')
result.append(">");
else if (character == '\"')
result.append(""");
else if (character == '\'')
result.append("'");
else if (character == '\\')
result.append("\");
else if (character == '&')
result.append("&");
else {
//the char is not a special one
//add it to the result as is
result.append(character);
}
character = iterator.next();
}
return result.toString();
}

Categories