Using document.getElementsByClassName - javascript

I coded two lines of PHP that allow me to protect an email address.
$mymail=strrev($mymail);
$mymail=str_replace("#","<b>#</b>",$mymail);
echo "<span class='spdefense'>".$mymail."</span>";
totiko#gmail.com becomes moc.liamg<b>#</b>okitot in source code
The problem is that users can no longer copy and paste e-mail addresses transformed in this way. So I want to create a javascript function that allows on a ctrl+c to:
Reverse string and remove <b> tags around # for all email adresses on a page.
No matter to reverse string and replace <b> tags. Mail adress is inside a span element with a class.
longueur=document.getElementsByClassName("spdefense");
for(var i= 0; i < longueur.length; i++)
{
machaine= document.getElementsByClassName("spdefense")[i].textContent;
machaine.split().reverse().join();
machaine.replace("<b>#</b>", "#");
}
I looked at "copy" and "clipboard" but I can't produce a valid code, to tell the truth I'm not sure if can be done...

A few things:
You want to re-use the longueur variable, as that's more efficient than grabbing all the classes twice.
You want to define it in the local block scope, not in the global one, using the const keyword.
You want to use the spread operator [...] to convert the string to an array of characters.
You want to join on an empty string .join(''), as the default for join is to use commas ,.
You want to save the result back to a variable.
You want that variable, machaine, to also be block scoped, rather than globally scoped.
You want to export the result out of the loop somehow, using an array, output, in the below example, seems appropriate.
const longueur = document.getElementsByClassName("spdefense");
const output = [];
for(var i = 0; i < longueur.length; i++)
{
const machaine = [...longueur[i].textContent].reverse().join('');
output.push(machaine.replace("<b>#</b>", "#"));
}
console.log(output);
That should work a little better... I haven't tested it, but it seems right.
As for the copy & paste, you can take a browse of the API documentation over at MDN.
The long and short of it is that you can use something like:
function setClipboard(text) {
const type = "text/plain";
const blob = new Blob([text], { type });
const data = [new ClipboardItem({ [type]: blob })];
navigator.clipboard.write(data).then(
function () {
/* success */
},
function () {
/* failure */
}
);
}
On a button click, which will add whatever text is, to the users system clipboard. There are permission considerations to take in to account, but chrome has it enabled by default (IIRC).

You can write to the clipboard via:
navigator.clipboard.writeText()
Consequently, when a user copies an email address, you can:
grab the obfuscated contents of the <span> which registered the copy event
deobfuscated those contents
write the deobfuscated contents to navigator.clipboard
Working Example:
const obfuscatedEmail = document.getElementsByClassName('obfuscated-email')[0];
obfuscatedEmail.addEventListener('copy', (e) => {
e.preventDefault();
let deobfuscatedEmail = e.target.textContent.split('').reverse().join('');
navigator.clipboard.writeText(deobfuscatedEmail);
});
textarea {
display: block;
width: 300px;
height: 60px;
margin-top: 12px;
resize: none;
}
<h2>Copy and Paste the obfuscated email below:</h2>
<span class="obfuscated-email">moc.liamg<b>#</b>okitot</span>
<textarea></textarea>

Related

How do I update the value of a custom attribute (enum-of-strings) in SFCC via code?

Requirement: I want to update the value of a custom attribute (name: badges) (type: enum-of-strings) for a Product via code. I want to set the value "bestSeller" as selected. How should I do that update because the code below is not working?
Screenshot of the Custom Attribute in Business Manager
Code snippet:
function updateBestSeller() {
var ProductMgr = require('dw/catalog/ProductMgr');
var Site = require('dw/system/Site');
var UUIDUtils = require('dw/util/UUIDUtils');
var CustomObjectMgr = require('dw/object/CustomObjectMgr');
var currentSite = Site.getCurrent();
var bestSellerOrderUnits = Object.hasOwnProperty.call(currentSite.preferences.custom, 'bestSellerOrderUnits') ? currentSite.getCustomPreferenceValue('bestSellerOrderUnits') : 0;
try {
Transaction.wrap(function () {
var count = 1;
var products = ProductMgr.queryAllSiteProducts();sni
var HashSet = require('dw/util/HashSet');
var badges = new HashSet();
if (products.count > 0) {
while (products.hasNext() && count < 5) {
var product = products.next();
var badges = [];
badges.push('bestSeller');
if (Object.hasOwnProperty.call(product.custom, 'badges')) {
product.custom.badges = badges
}
count++;
Logger.debug('{0}',product.ID);
}
}
products.close();
});
} catch (ex) {
Logger.error(ex.toString());
return new Status(Status.ERROR, 'ERROR', 'UPDATE failed');
}
return new Status(Status.OK, 'OK', 'UPDATE successful');
}
I think what is probably happening here is that your attempt to validate that a product has a badges key in the product.custom attribute collection is failing. This prevents the update from occurring.
I suggest removing the condition around the following line:
product.custom.badges = badges;
If that line were to not execute, then the update to the database would never occur.
The way custom attributes work is that they will never exist until a value is set for that attribute for a given persistent object. (eg: Product) So checking to see if it exists via something like: 'badges' in product.custom (which is the recommended way) will often be false even when the custom attribute definition exists because many products have never had a badge value set. Once an object has had a value set to a particular custom attribute even if it is now set to null then it will exist.
Additionally, there are some other issues with the code that may be causing problems. One example is defining the badges variable twice within the same scope. Another example is sni that is placed at the end of the line where you define the products variable. This is likely causing an error in your code. Finally, it is a good practice to avoid the use of the queryAllSiteProducts method if you can. An alternative may be to use the ProductSearchModel instead; This may not always meet your need, but it is a good idea to rule it out before resorting to queryAllSiteProducts for performance reasons.
Something else to consider is that if badges currently has any selected values, you'll be overwriting those values with the code you have today. Consider setting badges initially to [] then check to see if there is a value for that product by doing:
if ('badges' in product.custom && !empty(product.custom.badges) {
badges = product.custom.badges;
}

Add an object to JSON

I have a settings.json file that contains following data (where 123456789 is a distinct user id):
{
"123456789":
{"button_mode":true}
}
So what I need to do is push a similar id: {button_mode: value} object to this JSON file in case there's no entry for current user's id. I tried to use lcSettings.push() but obviously it did not work since I have an object, not an array. When I put square brackets instead of curly ones to make it an array, my code doesn't do anything at all.
Here's a snippet of it (Node.js):
var lcSettings = JSON.parse(fs.readFileSync('./settings.json', 'utf8'));
var currentUser = id;
if (lcSettings.hasOwnProperty(currentUser)) {
// in case settings.json contains current user's id check for button_mode state
if (lcSettings[currentUser].button_mode == true) {
// if button_mode is on
} else
if (lcSettings[currentUser].button_mode == false) {
// if button_mode is off
}
} else {
// in case there's no entry for current user's id
// here's where I need to push the object for new user.
}
fs.writeFileSync('./settings.json', JSON.stringify(lcSettings))
Does anybody have ideas on how it can be implemented? Any help appreciated.
You can use bracket notation to add a dynamic property to an object:
lcSettings[id] = { button_mode: false };
You may also want to verify that settings.json is not empty otherwise the JSON.parse() will fail. In this case, you would want to initialize lcSettings to an empty object (lcSettings = {}) so the above will work.
To 'push' elements to an object you simply define them, as in
object['123456789'] = { button_mode: true };

Replace particular file content in nodejs

I want to replace a particular line using javascript with new content.
This is the file content,
SERVER=1055#localhost
GROUP_SERVERS=2325#localhost
LINE_IAM_INTERESTED=KTYUIERVW:2800
FILE_PATH="C:\Program Files\somefile\Shared Files\"
In this line, LINE_IAM_INTERESTED=KTYUIERVW:2800 .I want to replace KTYUIERVW with KJHTERDY and 2800 with 78945
I have shown what I tried using fs appendfilesync
fs.appendFileSync('file_name').toString().split('\n').forEach(function(line){
app.console.log("called append");
var sEntry = line.split("=");
if (sEntry.length == 2) {
if (sEntry[0] == "LINE_IAM_INTERESTED") {
app.console.log("found one!!!!");
}
}
});
you can try READ -> REPLACE -> WRITE flow:
fs.writeFileSync('file_name', fs.readFileSync('file_name').replace('KTYUIERVW:2800', 'KJHTERDY:78945'))
appendFile and appendFileSync are used for adding to the end of the file. Although you can do it as a one liner as shown in the other answer, I've kept the structure of your code the same. Here you want to read the data, modify it then re-write it. Using the block of code you have, you can modify it to use readFileSync and writeFileSync.
let newData = fs.readFileSync('file_name', 'utf-8').split('\n').map(line => {
let sEntry = line.split('=')
if (sEntry.length == 2) {
if (sEntry[0] == "LINE_IAM_INTERESTED") {
console.log("found one!!!!");
return sEntry[0] + '=' + 'KJHTERDY:78945'
}
}
return line
}).join('\n')
fs.writeFileSync('file_name', newData)
I've swapped the forEach for map which lets us change the array data by returning the desired value. The new array is then joined back together and written back to the file.

How to remove any firebase data using JavaScript?

I am building a web application using JavaScript and firebase.
everytime I click on the "remove" paragraph tag, I can only remove the most recent added item, but cannot remove the rest.
Example: if I have 9 items, and I just added a 10th item, I can only remove the 10th item, but not the other 9 items. I basically can only remove items in a backwards order, as opposed to being able to remove items in any order of my choice.
Here is my code:
function displayFav(){
const dbRef = firebase.database().ref();
dbRef.on("value", (firebaseData) => {
// empty out element before adding new updated firebase data so there are no repeated data
document.getElementById("displayUsername").innerHTML = "";
let accounts = [];
const accountData = firebaseData.val();
for (let itemKey in accountData) {
accountData[itemKey].key = itemKey;
accounts.push(accountData[itemKey])
const key = accountData[itemKey]["key"];
const password = accountData[itemKey]["password"];
let user = accountData[itemKey]["username"];
// code where I try to render results from page
document.getElementById('displayUsername').innerHTML += `
<li> Username: ${user} Password: ${password}</li>
<p id=${key}>Remove</p>
`;
// code where I try to remove the item
document.getElementById(key).addEventListener("click", function(){
removeItem(key)
})
}
});
}
This is my function to remove the firebase data:
function removeItem(itemToRemove){
const dbRef = firebase.database().ref(`${itemToRemove}`);
dbRef.remove();
};
What can I change or add to my code that will allow me to remove items in any order I want, instead of letting me delete only the most recent items?
Not trying to be rude, this is just a tip: Please indent/format your code well so that people can understand it without having to format it themselves. Usually when people see large code that's not well formatted, it throws them off (sometimes including me), and therefore they wouldn't want to continue to read or help you with the question.
Suppose you have a table called posts, and the structure looks like this:
that is:
{
<postId>: {
date: 1518925839059,
message: 'some message'
},
<postId>: {
date: 151892583967,
message: 'some message'
},
...
...
}
Suppose you want to delete the extra property of the first post, as circled in the picture, you must know the full path of the data:
firebase.database().ref('posts/-L5b1EZ1L_FycluzTIn8/extra').remove();
If you want to delete everything in post 1:
firebase.database().ref('posts/-L5b1EZ1L_FycluzTIn8').remove();
Or, if you want to delete every single post:
firebase.database().ref('posts').remove();

Prettify json data in textarea input

I've searched for this particular topic and couldn't find anything similar to it. If there is please close this and give a link.
I'm creating a json data api simulator. I want users to be able to copy and paste a json object request into a textarea where they can also modify it before sending it to the server.
Problem is json obj copy and patses often results in extra spaces and is never aligned properly, even with the pre tag. I also want a good color scheme applied to keys and values.
I've seen plugins, other questions and snippets of code, but they don't apply to textareas where the text is editable. Is there to keep it styled while in edit mode without it showing all the html tags that styled it? I want to be able to write it from scratch with javascript or jquery.
The syntax highlighting is tough but check out this fiddle for pretty printing a json object entered in a text area. Do note that the JSON has to be valid for this to work. (Use the dev console to catch errors.) Check jsLint for valid json.
The HTML:
<textarea id="myTextArea" cols=50 rows=10></textarea>
<button onclick="prettyPrint()">Pretty Print</button>
The js:
function prettyPrint() {
var ugly = document.getElementById('myTextArea').value;
var obj = JSON.parse(ugly);
var pretty = JSON.stringify(obj, undefined, 4);
document.getElementById('myTextArea').value = pretty;
}
First try simple input like: {"a":"hello","b":123}
Simple pretty printing of JSON can be done rather easily. Try this js code: (jsFiddle here)
// arbitrary js object:
var myJsObj = {a:'foo', 'b':'bar', c:[false,2,null, 'null']};
// using JSON.stringify pretty print capability:
var str = JSON.stringify(myJsObj, undefined, 4);
// display pretty printed object in text area:
document.getElementById('myTextArea').innerHTML = str;
For this HTML:
<textarea id="myTextArea" cols=50 rows=25></textarea>
And check out JSON.stringify documentation.
Late answer but modern one, use the secret intendation parameter.
I usually go for:
JSON.stringify(myData, null, 4);
Here's the code definition, it explains it well.
stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
/**
* Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
* #param value A JavaScript value, usually an object or array, to be converted.
* #param replacer An array of strings and numbers that acts as a approved list for selecting the object properties that will be stringified.
* #param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
*/
For the parsing step you're just going to want to JSON.parse the contents of the textarea and handle any errors from bad input.
For the formatting part of your question, Use JSON.stringify(blob, undefined, 2). Alternatively, if you need colors here is a simple JSON format/color component written in React:
const HighlightedJSON = ({ json }: Object) => {
const highlightedJSON = jsonObj =>
Object.keys(jsonObj).map(key => {
const value = jsonObj[key];
let valueType = typeof value;
const isSimpleValue =
["string", "number", "boolean"].includes(valueType) || !value;
if (isSimpleValue && valueType === "object") {
valueType = "null";
}
return (
<div key={key} className="line">
<span className="key">{key}:</span>
{isSimpleValue ? (
<span className={valueType}>{`${value}`}</span>
) : (
highlightedJSON(value)
)}
</div>
);
});
return <div className="json">{highlightedJSON(json)}</div>;
};
See it working in this CodePen:
https://codepen.io/benshope/pen/BxVpjo
Hope that helps!
If you are a jquery fan, you can also use this small plugin I wrote:
// The plugin
$.fn.json_beautify= function() {
this.each(function(){
var el = $(this),
obj = JSON.parse(el.val()),
pretty = JSON.stringify(obj, undefined, 4);
el.val(pretty);
});
};
// Then use it like this on any textarea
$('textarea').json_beautify();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea id="myTextArea" cols=50 rows=5>{"name":"John","age":30}</textarea>
<textarea id="myTextArea2" cols=50 rows=5>{"name":"Bob","age":55}</textarea>
UPD
Changed code to multiselected elements.
I don't think that can be done with regular textareas. What you can do (and how most online code editors do it) is to create a transparent textarea that overlays on top of a div that contains the styled code. The user would still be able to type and interact with the input (and it fires the associated form events), and you can show syntax highlighting in the div that the user will visually see
(see Textarea that can do syntax highlighting on the fly?)
Now as for JSON formatting, I would add custom events to the textarea so that when a user types or paste something, run it through a Javascript JSON prettifier (see How can I pretty-print JSON using JavaScript?) and then re-populate the div and textarea accordingly
Here's a recursive function to return an object if it has been stringified multiple times:
const jsonPrettify = (json) => {
if (typeof json === 'object' && json !== null) {
const pretty = JSON.stringify(json, undefined, 4);
return pretty;
}
try {
const obj = JSON.parse(json);
return jsonPrettify(obj);
} catch (e) {
return json;
}
};

Categories

Resources