2 ways to disable chrome autocomplete on input fields

Google Chrome by default autocomplete the input field. The HTML autocomplete attribute no longer works on chrome. We present to you 2 methods you can use to disable the autocomplete feature for input fields in chrome and other browsers.

  1. Set input DOM value
  2. Use textarea (recommended)

1. Set input DOM value

When the page loads, wait for half second, then set the input value to empty.

<input type="text" name="username" id="disable-autocomplete" />

<script>
	window.addEventListener("load", function () {
		setTimeout(function () {
			document.getElementById("disable-autocomplete").value = ""
		}, 500)
	})
</script>

We are using wait for 0.5 seconds to let the chrome autocomplete set the value. Then we will override that value to empty.

2. Use textarea (recommended)

We can also use a textarea tag instead of the input field, which will look exactly like a standard input field.

<textarea name="username" rows="1"
	style="resize: none;
		min-height: fit-content;
		font-family: sans-serif;
		font-size: 14px;"

	oninput="this.value = this.value.replace(/\n/g, '')"></textarea>

resize: none; will remove the resize icon to the bottom right of textarea.

Some CSS frameworks like bootstrap give minimum height to a textarea field. You can override that value by setting min-height: fit-content; style.

To set the font the same for input fields, we are setting the font family to “sans-serif”, and size to “14px”. If you are using any framework like Bootstrap, you need to give the “inherit” property to “font-family”, “font-size”, and “font-weight”. This will take the font from its parent element.

rows=”1″ attribute is necessary as it will only make the textarea look like 1 row.

Finally, we are adding an attribute oninput that will be an event listener. This will be called whenever the element gets the user input. We are using a regular expression to convert all the new line characters to empty. This means we are disabling the enter key press. Otherwise, a new line would be started whenever the user presses enter key in the textarea.

Textarea as password

If you want to have your <textarea> tag to be treated as password input field, you can do it the following way:

<textarea name="password" rows="1"
    style="resize: none;
        min-height: fit-content;
        font-family: sans-serif;
        font-size: 14px;"
    id="maskedPassword"></textarea>
    
<input type="hidden" id="hiddenPassword" />

Then in Javascript, you need to do the following:

const maskedPassword = document.getElementById('maskedPassword')
const hiddenPassword = document.getElementById('hiddenPassword')

maskedPassword.addEventListener('input', function (event) {
    const input = event.target.value
    
    // Prevent adding asterisks to the hidden input value
    if (input.length > hiddenPassword.value.length) {
        const newChar = input[input.length - 1]
        hiddenPassword.value += newChar
    } else {
        hiddenPassword.value = hiddenPassword.value.slice(0, input.length)
    }

    maskedPassword.value = '*'.repeat(input.length)
})

Explanation:

  • <textarea>: First we create a <textarea> tag where user will enter his password. Whatever user enters here will be replaced with asterisk “*”.
  • <input />: Then created a hidden input field where the actual password value will be stored.
  • In Javascript, we get DOM of both <textarea> and hidden <input> field.
  • Attach an input event listener to the <textarea> that will be called whenever user type anything in it. This will also be called if user copy/paste something in it.
  • Line 5: Getting the value of <textarea>.
  • Line 8: Make sure the length of <textarea> should be 1 character greater than the hidden <input> field.
  • Line [9-10]: Get the last character of textarea and append it in hidden input field.
  • Line 12: If textarea value is less than hidden input field, meaning user has pressed backspace or remove some characters, then replace the hidden input field value to where it was before (last entered value).
  • Line 15: Replace every character in textarea with asterisk “*”.

Disable copy, cut and paste

As this is a password field, so you must not allow users to copy, cut or paste from that input field. You can disable copy, cut and paste features on password field.

// Disable copying, cutting, and pasting
maskedPassword.addEventListener("copy", function (event) {
    event.preventDefault()
    // alert("Copy is disabled!")
})

maskedPassword.addEventListener("cut", function (event) {
    event.preventDefault()
    // alert("Cut is disabled!")
})

maskedPassword.addEventListener("paste", function (event) {
    event.preventDefault()
    // alert("Paste is disabled!")
})

That’s how you can disable autocomplete for input fields in Google Chrome along with disabling copy, cut and paste feature.

Disable autocomplete on textarea

If you are using <textarea>, you will notice that it also has an autocomplete feature. To disable the autocomplete feature on textarea, you need to do 2 things:

  • Set readonly attribtue as soon as textarea gets focused.
  • Remove readonly attribute just after 10 milliseconds.
<textarea name="address" id="address"></textarea>

<script>
    document.getElementById("address").addEventListener("focus", function() {
        const self = this;
        this.setAttribute("readonly", true);
        setTimeout(function () {
            self.removeAttribute("readonly");
        }, 10);
    });
</script>

If you set readonly attribute on textarea tag, the autocomplete feature does not work. But that means that user is also not able to type anything in textarea field. So you remove the readonly attribute right after 10 milliseconds that will not be noticeable by users.

If you face any problem in following this, kindly do let me know. Check out our tutorial to disable mouse scroll on input number fields.

Practical difference between async await and callback

In one of our tutorial, we learned how to create a function in async await and how to create a function that uses callback.

Video tutorial:

Asynchronous

Let’s say you want to send an email to a user. Following is a Node JS code that sends an email using a callback:

const transport = nodemailer.createTransport({
	host: "",
	port: 465,
	secure: true,
	auth: {
		user: "",
		pass: ""
	}
})

transport.sendMail({
	from: "support@adnan-tech.com",
	to: "",
	subject: "Test",
	text: "Hello",
	html: "Hello"
}, function (error, info) {
	console.log("Mail sent: " + (new Date()))
})

console.log("I am called: " + (new Date()))

In your terminal, you will see that the “I am called:” message will be displayed instantly. But the “Mail sent:” message will be shown after a few seconds, once the mail is sent. It means that all lines of your code are executed at once, irrespective of the fact that the sendMail function will take some. The code is executed without waiting for any function to complete. This is asynchronous programming.

Synchronous

This can be converted into a synchronous function. Following is the synchronous version of the above code:

// the function must be async if await is used inside it

app.get("/sendMail", async function (request, result) {

	// send an email using a callback
	const transport = nodemailer.createTransport({
		host: "",
		port: 465,
		secure: true,
		auth: {
			user: "",
			pass: ""
		}
	})

	const info = await transport.sendMail({
		from: "support@adnan-tech.com",
		to: "",
		subject: "Test",
		text: "Hello",
		html: "Hello"
	})

	console.log("Mail sent: " + (new Date()))

	console.log("I am called: " + (new Date()))

	result.send("")
})

If you run the code now, you will have to wait for the sendMail function to finish before you see your log messages. This is synchronous programming.

Now you have understood the difference, let’s discuss where you should use async await and where you should use a callback.

When to use async await

You should use the async await pattern when the next line of your code is dependent on the previous lines. For example, “you have to insert the record in the database only if the mail is sent successfully”. In this case, you must use async await so that your code will wait for the mail to be sent successfully, then it will insert it in the database.

When to use callback

A callback will be helpful when your code sections are independent of each other. For example, “send an email to the user and insert the record in the database.” In this case, your insertion query should not have to wait for the mail to be sent. The mail should be handled in a callback.

A guide to MEVN

MEVN stands for Mongo DB, Express JS, Vue JS, and Node JS. It is a technology stack used by developers to create full-fledged web applications. Most of the applications created in the MEVN stack are single-page applications. But it is up to you if you want to single page or multi-page web application.

Table of content

  1. What is MEVN ?
  2. Why MEVN ?
    • Same language for frontend and backend
    • Easy deployment
    • Seamless user experience
    • APIs for mobile apps
    • Mongo DB is scaled horizontally
    • Short learning curve
    • Better support for sockets
  3. Future of MEVN
  4. Projects developed in MEVN
  5. Where to learn MEVN ?
    • Official documentation
    • YouTube
    • Blogs
  6. Issues you will face in the development

Let’s get started.

1. What is MEVN ?

MEVN is a technology stack used to develop full-fledged web applications. You can easily create scalable web applications either single-page or multi-page applications. It is a new yet quickly evolving technology stack that has been adopted by a lot of developers already. Learning this will not only make you a frontend developer but a backend developer as well. Thus increasing your demand and reputation in the community.

Hiring a developer in this stack is easy for companies as well. Hiring individual developers for the backend and frontend is costly, especially for startups. So they end up looking for someone who knows both the backend and frontend.

2. Why MEVN ?

If you learn this technology stack, your demand is automatically increased since companies would love to have a developer that can handle both frontend and backend tasks. Even if you didn’t get a job as a full-stack developer, you can still get a job as either a frontend or backend developer since you can work in both.

Same language for frontend and backend

In this stack, the primary language is Javascript. Node JS is a Javascript runtime environment, Vue JS is a Javascript frontend framework and Express JS is a framework of Node JS for creating APIs. Mongo DB syntax is also very similar to Javascript. So you do not need to learn Javascript for the frontend and PHP or Python for the backend. One language i.e. Javascript is used for both sides (frontend and backend).

Easy deployment

Vue JS builds are minified code of HTML, CSS, and Javascript. So they can easily be deployed on most servers. You do not need to worry if your hosting supports PHP, Java, Python, or any other language. If your hosting supports HTML (which almost every hosting does) then you are good to go.

Node JS can also be easily deployed on Virtual Private Servers (VPS) or dedicated servers. You can check our detailed guide on how to deploy Node JS on VPS or dedicated servers.

Mongo DB can also be deployed on VPS or dedicated servers. But it can also be deployed on Mongo DB’s official site. You can check our tutorial for Mongo DB deployment.

Seamless user experience

Most of the apps created in this stack are single-page applications. They provide a better user experience since there is no page reload on any link. Only the required section of the page changes dynamically. Some of the websites that are single-paged are Gmail, Facebook, and Twitter.

APIs for mobile apps

Most of the rendering is done on the client side. This means you have to create APIs for each request. This helps you in the future when you want to develop mobile apps for your website. Android and iOS apps can easily communicate with APIs developed in Node JS.

Mongo DB is scaled horizontally

Horizontal scaling is performed by adding more nodes to the servers. Horizontal scaling is best for a non-relational database like Mongo DB since all the data is stored in a single document.

Moreover, if you have to add one more attribute to a single entity, you can easily add it to that document only. Unless in MySQL, where either you have to create a column that will result in assigning the value to all rows. Or you have to create a separate table and join them in each query which will slow down your application.

In Mongo DB, all data required for an entity is stored in a single document. No relationships are made. So data can be saved on different servers without being dependent on each other.

Short learning curve

If you know Javascript, you already know Vue JS. Unlike in React where you have to use JSX syntax, in Vue JS you can use legacy HTML and CSS code and use Javascript with it. If you know the basics of Javascript, spend a few hours on Vue JS official documentation and you will become a Vue JS developer.

Better support for sockets

Sockets are used for real-time communication. Like on Facebook, you do not have to refresh the page to check new notifications. Whenever a new notification is received, it automatically displays an alert. If you develop your web application in the MEVN stack, you will be able to add real-time features like alerts, notifications, chat messages, real-time collaborations, etc.

3. Future of MEVN

MEVN proving itself a bright future. A lot of developers are moving to this stack. It is in the race with MEAN and MERN stacks. It has solved a lot of issues that developers faced in web development. For example, during infinite scroll, the web page hangs due to too much data. Vue JS solved this by using the useVirtualList component. Node JS has solved real-time communication problems via sockets. And Mongo DB has solved the scalability problems and also the problems that came with tightly-coupled databases.

4. Projects developed in MEVN

To show you how easy it is to develop websites in this technology stack, we developed some projects in it. We have developed a chat app, a customer support ticketing system, and more.

5. Where to learn MEVN

You can learn this technology stack from many sources.

Official documentation

To stay updated with the latest versions and features, check out the official documentation of Vue JS. Node JS can also be learned from their official documentation. Mongo DB also came with outstanding documentation.

YouTube

Check this playlist to find a lot of tutorials on the MEVN stack.

Blogs

We have created many text-based tutorials on this stack.

6. Issues you will face in the development

You need to spend a lot of time to make the application up and running. The first version of your product might take more time and effort because you need to set up the APIs and basic functionality. However, we have created a boilerplate for authentication that will save you 100% time on rewriting the authentication code.

How to pick random document from Mongo DB

We need to use the aggregate function to pick a random document from Mongo DB. Its usage is simple. It accepts an array of objects. You need to pass $sample object in one array object and tell the number of random documents you want to fetch in the size object. Suppose you have the following data in your users collection.

db.users.insertOne({ name: "Adnan", language: "Java" })
db.users.insertOne({ name: "Tech", language: "Node JS" })
db.users.insertOne({ name: "Developer", language: "Java" })
db.users.insertOne({ name: "Programmer", language: "C++" })

Then the Mongo DB query to return 1 random document would be:

db.users.aggregate([
	{
		$sample: {
			size: 1
		}
	}
])

This will return 1 random document from your users collection. If you want to apply some query to it, you can do it by passing another array element and this time using the $match operator.

db.users.aggregate([
	{
		$match: {
			language: "Java"
		}
	},
	
	{
		$sample: {
			size: 1
		}
	}
])

This will return 1 random document from users collection whose language is “Java”. Make sure the $match operator is the first element of the array, otherwise it will return empty records sometimes.

Video tutorial

You can learn more about Mongo DB aggregate function from their official documentation. Check out our tutorials on Mongo DB.

Add or update URL query parameter in Javascript

Create the following function in Javascript to add or update URL query parameter.

function addOrUpdateURLParam (key, value) {
    const searchParams = new URLSearchParams(window.location.search)
    searchParams.set(key, value)
    const newRelativePathQuery = window.location.pathname + "?" + searchParams.toString()
    history.pushState(null, "", newRelativePathQuery)
}

Now, whenever you want to add or update the URL, simply call the function in the following way:

addOrUpdateURLParam("name", "adnan-tech.com")

The first parameter will be the key of the parameter, and the second will be the value.

window.location.search: will return all the query parameters starting from “?”.

URLSearchParams: This will create an instance of URLSearchParams that will be used to manipulate URL query parameters.

searchParams.set(key, value): This will set the key value provided in arguments, but will not display yet in the URL.

window.location.pathname: It returns the relative path starting from “/your_website”. It DOES NOT include the query parameters starting from “?”.

searchParams.toString(): Will convert all the key-value pairs to a string. If there will multiple parameters set, then they will be separated by the “&” sign.

history.pushState: Will actually display the query parameters in the URL.

The first parameter to the “history.pushState” function is the “state”. It can be a push, pop, or null. The second parameter is not used anymore but not removed either, passing an empty string is safe. The third parameter is the new URL, here we are passing our new string variable to set the new URL with query parameters. More information can be found here.

Video tutorial:

Following this tutorial, I hope you will be able to add or update query parameter in your website’s URL using Javascript. If it helps, check out our tutorials on Javascript.

Pass value from recycler view adapter to activity – Android Kotlin

In this tutorial, we will teach you how you can pass value from the recycler view adapter to activity in Kotlin. First, you need to create an interface:

// file name = RVInterface.kt

package com.adnantech.myapp

import android.view.View

interface RVInterface {
    fun onClick(view: View)
}

Here, “RVInterface” is short for “Recycler View Interface”. Now, suppose we have the following model class:

// file name = User.kt

package com.adnantech.myapp

class User(val name: String) {
    //
}

And we create an array list of 3 users.

val users: ArrayList<User> = ArrayList()
users.add(User("Adnan"))
users.add(User("Tech"))
users.add(User("Developer"))

Then you need to create an instance of your interface in your activity class:

private val rvInterfaceInstance: RVInterface = object : RVInterface {
    override fun onClick(view: View) {
        val index: Int = recyclerView.getChildAdapterPosition(view)
        if (users.size > index) {
            Log.i("mylog", users[index].name)
        }
    }
}

This will override the “onClick” function created in the interface. When this function is called, it will get the item’s index in the recycler view. Check the index must not be outbound in the “users” array. Then display the user name in logcat.

After that, you need to pass this interface instance to your adapter:

val adapter: UsersAdapter = UsersAdapter(users, rvInterfaceInstance)

Since we are sending the interface instance as a parameter, so we can easily get it in our adapter’s constructor:

class UsersAdapter(
    private var users: ArrayList<User>,
    private var rvInterfaceInstance: RVInterface
)

And finally in your adapter, inside the “onBindViewHolder” method, we can call the following function to call the interface method inside the activity class:

holder.itemView.setOnClickListener {
    rvInterfaceInstance.onClick(holder.itemView)
}

This will call the interface method when the item in the adapter is clicked. But you can add it to any button click listener as well.

Download files in storage – Android kotlin

Previously, we created a tutorial to show you how you can download an image in your storage using Java. In this tutorial, we will show you how you can download any file in your android phone’s storage using Kotlin. First, you need to create a file named “DownloadImageTask.kt” and write the following code in it:

class DownloadImageTask(
    var imagePath: String?,
    var fileName: String?
) : AsyncTask<Void, Void, Void>() {

    var cachePath: String = ""

    override fun doInBackground(vararg voids: Void?): Void? {
        try {
            val root =
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
            val directoryPath = File(root.absolutePath + "/")
            if (!directoryPath.exists()) {
                directoryPath.mkdir()
            }
            val cachePath = File("$directoryPath/$fileName")
            cachePath.createNewFile()
            val buffer = ByteArray(1024)
            var bufferLength: Int
            val url = URL(imagePath)
            val urlConnection = url.openConnection() as HttpURLConnection
            urlConnection.requestMethod = "GET"
            urlConnection.doOutput = false
            urlConnection.connect()
            val inputStream = urlConnection.inputStream
            val fileOutput = FileOutputStream(cachePath)
            while (inputStream.read(buffer).also { bufferLength = it } > 0) {
                fileOutput.write(buffer, 0, bufferLength)
            }
            fileOutput.write(buffer)
            fileOutput.close()
            inputStream.close()

            this.cachePath = cachePath.toString()
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        } catch (e: ProtocolException) {
            e.printStackTrace()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return null
    }

    override fun onPostExecute(aVoid: Void?) {
        // when the operation is done
        // you can use this.cachePath here
    }
}

Now, whenever you want to download any file, you just need to run the following line passing the file’s absolute path in the first parameter. And the file name as the second parameter. The second parameter file name will be the name that will be saved in your phone’s storage.

DownloadImageTask("https://www.nasa.gov/sites/default/files/styles/full_width_feature/public/thumbnails/image/stsci-01gfnn3pwjmy4rqxkz585bc4qh.png", "nasa.png")
                .execute()

That’s how you can download any HTTP file in your android phone’s storage using Kotlin. If you face any problem in following this, kindly do let me know in the comments section below.

Display HTTP images in ImageView – Android kotlin

In this tutorial, we will show you how you can display HTTP images in your ImageView in your android app using Kotlin. We will be displaying this image “https://www.nasa.gov/sites/default/files/styles/full_width_feature/public/thumbnails/image/stsci-01gfnn3pwjmy4rqxkz585bc4qh.png” in our image view.

Then create a file named “FetchImageFromInternet.kt” and write the following code in it:

package com.adnantech.myapp

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.AsyncTask
import android.util.Log
import android.widget.ImageView
import android.widget.Toast

@SuppressLint("StaticFieldLeak")
@Suppress("DEPRECATION")
class FetchImageFromInternet(var imageView: ImageView) : AsyncTask<String, Void, Bitmap?>() {
    init {
//        Toast.makeText(applicationContext, "Please wait, it may take a few minute...",     Toast.LENGTH_SHORT).show()
    }
    override fun doInBackground(vararg urls: String): Bitmap? {
        val imageURL = urls[0]
        var image: Bitmap? = null
        try {
            val `in` = java.net.URL(imageURL).openStream()
            image = BitmapFactory.decodeStream(`in`)
        }
        catch (e: Exception) {
            Log.e("Error Message", e.message.toString())
            e.printStackTrace()
        }
        return image
    }
    override fun onPostExecute(result: Bitmap?) {
        imageView.setImageBitmap(result)
    }
}

And this will be your image view:

<ImageView
    android:id="@+id/imageView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scaleType="fitCenter" />

Then whenever you want to display an HTTP image, just write the following lines:

val imageView: ImageView = findViewById(R.id.imageView)

FetchImageFromInternet(imageView)
    .execute("https://www.nasa.gov/sites/default/files/styles/full_width_feature/public/thumbnails/image/stsci-01gfnn3pwjmy4rqxkz585bc4qh.png")

Run the app now and you will be able to view that HTTP image in your app. Check out our more tutorials on android.

Select file from internal storage – Android kotlin

To select a file from internal storage in android using Kotlin, first, you have to start an intent with a request code.

val intent = Intent(Intent.ACTION_PICK)
intent.type = "*/*"
startActivityForResult(intent, 565)

After that, when the image is selected from the gallery by the user, it will be received in the onActivityResult method. So we need to create the following methods in our activity:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (resultCode == Activity.RESULT_OK && requestCode == 565) {
        val uri: Uri? = data?.data

        var base64: String = ""
        try {
            val bytes = uri?.let { contentResolver.openInputStream(it)?.readBytes() }
            base64 = Base64.encodeToString(bytes, Base64.URL_SAFE)
        } catch (e1: IOException) {
            e1.printStackTrace()
        }

        var attachmentName: String = uri?.let { getFileName(it, contentResolver) }.toString()

        var extension: String = uri?.let {
            getMimeType(
                applicationContext,
                it
            )
        }.toString()

        Log.i("mylog, base64 = ", base64)
        Log.i("mylog, attachment = ", attachmentName)
        Log.i("mylog, extension = ", extension)
    }
}

fun getFileName(uri: Uri, contentResolver: ContentResolver): String {
    val returnCursor: Cursor = contentResolver.query(uri, null, null, null, null)!!
    val nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
    returnCursor.moveToFirst()
    val name = returnCursor.getString(nameIndex)
    returnCursor.close()

    return name
}

fun getMimeType(context: Context, uri: Uri): String? {
    return if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
        //If scheme is a content
        val mime = MimeTypeMap.getSingleton()
        mime.getExtensionFromMimeType(context.contentResolver.getType(uri))
    } else {
        //If scheme is a File
        //This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file name with spaces and special characters.
        MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(File(uri.path)).toString())
    }
}

Run the app now, you will be able to select any file from your internal or external storage (if you have external storage). After you select the file, you will see its base64 content, file name, and its extension in the logcat of android studio.

Pass headers with Volley – Android kotlin

In the Android Volley library, you can pass headers with an HTTP request using Kotlin. Headers are used to pass additional information. Following will be the code to pass headers with the Volley library:

val queue = Volley.newRequestQueue(this)
val url = "http://172.20.10.4:3000/getUser"

val requestBody = ""
val stringReq: StringRequest =
    object : StringRequest(
        Method.POST, url,
        Response.Listener { response ->

            Log.i("mylog", response)

        },
        Response.ErrorListener { error ->
            Log.i("mylog", "error = " + error)
        }
    ) {
        override fun getHeaders(): MutableMap<String, String> {
            val headers = HashMap<String, String>()
            headers["Authorization"] = "Bearer {your_access_token}"
            return headers
        }

        override fun getBody(): ByteArray {
            return requestBody.toByteArray(Charset.defaultCharset())
        }
    }
queue.add(stringReq)

If you want to see how you can handle headers in the backend in Node JS, you are free to check our GitHub repo.