Keep sending a string without breaking changes on this NPM library - javascript

A little bit of backstory:
We're trying to address a bug on a local library we have.
I was trying to convince the senior developers of changing naming convention when using word like these:
enable disable hide unhide
because they were using
enable disable hide undelete
We discussed the fact of this being a breaking change and will stop other products from working.
So it was disscused to add the unhide without taking the undelete out so that it does not break anything and in the process, if the user uses either unhide or undelete they should still do the same in theory.
Here comes the programming problem now:
This is my function:
toggleAction(data._id, 'undelete', (err, data) => { // cool stuff }, false)
How can I continue to pass a string (without converting to an array or object) but also start passing 2 values so that the changes have to be made in this file and not in the projects side validating, etc.
Another thing, this function will default if the switch case does not found the string.
Also thought about sending two request at the same time but that's just bad programming.
Also though of fallback to another request with the other naming, but since the switch case will still default if it's not in the options, it will not throw an error to actually do the callback for the next function.
What do you guys think is the right approach for something simple and yet capable of breaking a lot of things.
Thanks in advance.

Kinda opinion based, but it's the wrong approach imho.
I would change the word undelete to unhide only on the rendered websites and keep the internal API the same way until the senior devs can fix the breaking changes.
So the user would see the word 'unhide' on their screen, but the API will still stay 'undelete'.
In more complex applications, you'd use an enumeration list so you can change the labels as many times as you want:
const enum_options = [
'enable',
'disable',
'hide',
'show'
];
// 3 is the index of the word 'show'
toggleAction(data._id, 3, (err, data) => { // cool stuff }, false)
That way the API never has to change when you change the labels to any word you desire. Which will also help alot if you ever have to support multiple languages.
ps:
1) if this is a breaking change, there's an issue with the architecture used.
Fix the issues instead of adding even more fragile code. Switching to like using a string 'undelete-unhide' will still need alot of api changes if the entire app has the word 'undelete' written everywhere at the moment.
2) The opposite of hide is usually 'show', not unhide.

Related

Add some characters to the end of URL

I use a WordPress theme that has a number of custom post types. When I search for these post types, in the results page, the display order is from the oldest post to the newest post, but I want the newer posts to be displayed first.
I didn't design this template, so I don't know how to code it.
I found that by putting orderby=new at the end of the URL of the site, the display order is fixed.
Is there a way to automatically add this phrase to the end of the URL when someone enters the results page?
The links are like this: mydomain.com/activites/?location_name=paris&location_id=&taxonomy%5Bst_tour_type%5D= to the phrase mydomain.com/activites/? It is constant in all searches and after that, it changes based on the term that the user searches for.
The word location is the post type and the rest of the parts that come in the url are taxonomy.
immediate answer:
Write the link to the page accordingly. All other solutions will require changing some of the code or settings.
From my understanding of your question the cleanest solution is probably just to include a link back to the page itself with an added &orderby=new
Label the link in a way that makes it obvious to the user what it does. In this case I would assume ordering some type of content by release or entry date.
recommended solution:
Change the script in way that makes that order the default. It seems to be what you ideally "want". But can't do. As implied by the question.
janky solution:
Add a redirect. It's the same thing I said before but automatic without user input. The only benefit to this is being able to avoid touching existing code. And apply to all users as default.
roundabout solution, that will make maintenance a nightmare long term:
Rewrite rules in your web server. If you don't have access to that: try .htaccess
But since this modifies the behavior in a not immediately obvious way if is missing. And this will be easily missed by merit of being a hidden file and this type of config override not always being allowed. This might lead to non intuitive problems in the future.

Writing Javascript tests without NodeJS

I've been struggling with going back to the roots of doing non-node reliant javascript, in this particular case for a test. Like many developers, i've fallen into the trap of learning frameworks, and in turn have forgotten / never understood some of the basic paradigms with javascript programming.
The problem
I'm trying to test a simple es6 script i've created for a collapsible element. It can be tested with a framework, however the script is simply inserted into the bottom of a html file, rather than be executed in any more complex way, and needs to remain functional without a complex procedure behind it. I understand that this is not the conventional way to do this, you could easily make the problem trivial with modern tech, but it's the way i'm required to put this together.
Collapsible.js
const initialiseCollapsible = (collapsible) => {
let collapsibleButton = collapsible.querySelector(".collapsible__button");
let collapsibleContent = collapsible.querySelector(".collapsible__content");
collapsibleButton.setAttribute("aria-expanded", "false");
collapsibleContent.setAttribute("aria-hidden", "true");
collapsibleButton.addEventListener("click", () => {
// cast the value of aria-expanded as a boolean
let expanded =
collapsibleButton.getAttribute("aria-expanded") === "false"
? false
: true;
// Toggle the expanded attribute
collapsibleButton.setAttribute("aria-expanded", !expanded);
collapsibleContent.setAttribute("aria-hidden", expanded);
});
};
(() => {
[...document.getElementsByClassName("collapsible")].forEach((collapsible) => {
initialiseCollapsible(collapsible);
});
})();
The file is meant to loop through all instances of .collapsible, adding event listeners so they can toggle correctly, and closing them initially (The content has to be accessible with javascript disabled).
1) Module functionality
With es6 moduling, i'm aware that it's transpiled normally using something such as babel. And with requireJS, I still don't understand whether module.exports is going to be understood by the browser, currently it throws errors because it doesn't understand the syntax. Is there a way of going around this? So I can write a functional script to be called in a html file, while still being able to import this into a test file to run tests on? I'm assuming I could just end up copy and pasting it for the sake of having it available is necessary.
2) Testing the thing
I'm struggling to contemplate how to test this piece of code accurately. I see a few potential tests:
Given a collapsible html element,
The expanded / hidden are correctly set to start (testing the query selector works and that the set attributes are working correctly)
Problem I don't quite understand how to emulate this without some sort of virtual dom that I can tamper with, are there good libraries for this? Ones that will allow me to create a document htmlelement that I can run the script code on to see the changes.
The collapsible button now has a clickEvent on it that matches the code of the example. Problem This feels almost like a functional test to me, i'm testing that something happens when I click the button, almost like cucumber / selenium would be a better route for this. There's a large amount of overhead there for something so simple however, is there an easier way to do this?
I realise this is probably around 10 questions in 1, but if you have any feedback / solutions for the problems posed, feel free to contribute.

How to lint specific function call in JavaScript?

My team has had the occasional problem of developers pushing Karma/Protractor tests containing the .only() function call, which of course makes our Jenkins etc only run that particular test, potentially allowing bugs to slip by. As such I thought I'd try and figure out a way to stop this from happening without being discovered.
First, I thought I'd look into simply using JSHint to point out the function call, but I can't seem to find a way to do that. I also looked at ESLint for its custom plugins, but I can't figure out how to write a plugin for this particular case.
Could you guys give me some ideas on how to solve this issue? Alternative solutions are also appreciated, of course!
Here's a (probably not working example) of how to create a plugin that flags an error if the parser ever sees a only() call. Again, mileage may vary, but it should be enough to get you started. This does not work if it sees a.only(), we'll leave that up to you.
module.exports.rules = {
"no-only-call": context => ({
CallExpression: (node) => {
if(node.callee.name == "only"){
context.report(node, 'Calls to only() are disallowed');
}
}
})
};
https://www.kenneth-truyers.net/2016/05/27/writing-custom-eslint-rules/ - Simple example of creating a custom rule
http://esprima.org/demo/parse.html - Use this online parser to help you understand the parse tree.
https://www.npmjs.com/package/generator-eslint - Use this generator to start your plugin project

How to organize JS functions using objects

I would like to know if organizing JS functions in object notation is a good or bad practice. The intention is to keep js organized/easy to maintain.
Example:
var helper = {
myAlert: function(){
return alert('Alert from helper');
},
toLowerCase: function(){
var str = document.getElementById("txt").innerHTML;
return alert(str.toLowerCase());
}
}
Html:
<body>
<h1 onclick="helper.myAlert()">Hello Plunker!</h1>
<p id="txt" onclick="helper.toLowerCase()">Testing LowerCaseFunction</p>
</body>
Plunker
Thanks in advance!!!
code organization is an strategic topic when it comes to make software survive more than a couple of years yet this is also a very opinionated terrain.
You can make a nice job by keeping semantically related functions near each other under the same namespace, or even make it related to the user story being solved, it can be done in many ways.
If you want to know this approach is good enough, simulate an iteration on it, add a new feature and see what happens to the code.
The code avoids duplication? It gets reusable? Is it easy to locate and relate with the user needs? If so, then it will help you.
Finally, if applicable consider to use some module builder, webpack or browserify for example, so you will be able to not only separate your modules logically but "physically" too.
For me it is a good practice. When working with little projects, you do do see it important, but in large projects you are almost obliged to do it.
simply imagine you are making a chat website, you will need to create function that will delete messages, add messages. you can simply do it as you did it up.
var messages = {
remove:function{//remove code},
add:function{//add code}
}
in this way you can define contacts management object as
var contacts = {
remove:function{//remove code},
add:function{ //add code},
block:function{//block code}
}
This isn't really an answer per se but too long for a comment:
Since you are asking about best practices I'd like to point out a few things in your sample:
onclick. Just...don't. You don't want to grep through your JS trying to diagnose a behavioral problem only to realize 8 hrs in that its being called from HTML. That's a maintenance nightmare waiting to happen.
innerHTML again, just...don't. Unless you are working with HTML. 9 times out of 10, textContent will do and you can assign to it without security risk. Google 'innerHTML security risk' for more info.
alert alert blocks. Blocks your whole browser until you click annoying box. And which of your 50 open tabs was it in? Blocking is bad. Use console.log. You're a dev, and you do have devtools open right?
Your toLowerCase function. You mix data access (getting the DOM element's text) with data transformation. Bad idea.
Note that none of these are particular to JavaScript, they apply to pretty much all UI coding: don't mix business logic with the presentation layer, don't block user interactions, use the principle of least privilege, don't mix data access with data processing, etc. And all of the above issues are bigger problems than whether or not you namespace some functions.

How to create a truly hidden variable in Javascript

I am trying to build a puzzle game using HTML & JS. This is going to be a standalone HTML page. There isn't going to be a server side for this application.
Obviously, the game has an answer which the application will create at start time. Now, I wish to make this variable completely hidden i.e., not just hidden from user's view but also inaccessible to the user, even if he tries to read the page through Chrome's Developer Tools or such debug tools.
I'm looking for a solution using HTML5, JS ECMAScript 5+ & jQuery.
I remember reading something about Native HTML code (used for HTML File elements) which cannot be rendered/read even through Dev Tools. Is this any help?
Is there any way or strategy to achieve this?
NOTE: I am aware of <input type="hidden">. But that doesn't serve my purpose.
EDIT: As part of the game, the user makes attempts and the application needs to validate the user's input against this somehow-user-hidden answer variable. At this point, I believe there is no solution that's going to be completely airtight in the given constraints. Hence, I'm pursuing this from an academic interest. Does anyone have any other answers ?
Prehash your answer, hard code that into your page.
Then, when they submit their answer, run through whatever hashing pattern you did before hand, and compare the result.
It could theoretically be brute forced, of course.... if you had a few hundred years.
Javascript implementations of:
SHA-1: http://www.webtoolkit.info/javascript-sha1.html
SHA-256: http://www.webtoolkit.info/javascript-sha256.html
MD5: http://www.webtoolkit.info/javascript-md5.html
Edit:
An example would be:
Pattern: SHA-1(SHA-1(SHA-1(answer + salt)))
Salt: 982qx17wef7ddsbtxaewnsdufs (make something up, load it as an input type='hidden')
Result: (load it as an input type='hidden')
Request the answer
If SHA-1(SHA-1(SHA-1(attempt + salt))) === Result, they got it correct
Your can hash your values using MD5.
https://github.com/blueimp/JavaScript-MD5#client-side

Categories

Resources