How to resend SMS verification in Firebase Phone Authentication?

We all know that feeling. You don’t have a concrete idea about the solution you are looking for and you want to see a quick answer for your question. So, check the short answer below:

Short answer to your question

Very short answer is a “NO”. Firebase PhoneAuthProvider does not deliver a resend SMS feature in its SDK for JavaScript developers (as of now, June-2019). It actually supports such feature for Android, C++ and Unity developers via PhoneAuthProvider.ForceResendingToken, but the same is not available for JavaScript developers. Therefore, if you’d like to create a “Resend SMS Verification” button for your web application, you should implement it yourself by initialising a new recaptcha session (like setting window.recaptchaVerifier etc…), using a separate recaptcha container (such as <div id=”recaptcha-container-resend” />) and eventually calling signInWithPhoneNumber(…) function again on user interaction.

Long answer to your question

The screenshot below shows you the documentation of Firebase services in various platforms. You may access the Javascript SDK reference by clicking the link below:

https://firebase.google.com/docs/reference/js

Screenshot 2019-06-16 at 17.12.00

To implement a resend SMS feature on my ReactJS app, I went through this documentation. And I realised that there wasn’t any resend SMS support by Firebase.auth. Interestingly, there was no blog or stackoverflow ticket discussing the issue either. Then, I assumed that the developers, who came across with the same problem, silently implemented a resend SMS feature by simply re-initialising the whole process on their web applications. Therefore, I decided to break this silence by writing this post and helping future developers (and maybe even future self 🙂 ).

Assume that your application shows two components to the user. First component will receive the phone number from the user and after the SMS is sent, the second component will demand the user to type in the verification code.

Your first component should run following methods in order:

  1. Initialize recaptcha
    • window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier(…);
  2. Sign in with given phone number
    • auth.signInWithPhoneNumber(phoneNumber, appVerifier);
  3. Reset or even remove recaptcha
    • grecaptcha.reset(window.recaptchaWidgetId);

Above is a rough sequence of the operations that you should follow and I believe you already know how these work.

When your application moves to the second component, you may wish to use the existing implementation (the functions in the first component) by passing the functions as arguments in React. However, this approach creates some trouble for the RecaptchaVerifier, because you already used the recaptcha session to send the first SMS and if your user attempts to send the SMS again, you will need a new recaptcha session. Plus, you will also need a recaptcha container in your second component as well. Recaptcha container is the place that grecaptcha-badge will be loaded in an iframe. In order to avoid these conflicts, I have implemented the same set of methods in the second component as well. And to prevent any other potential conflicts, I created a separate recaptcha-container with a new id.

First component’s container:

<div id=”recaptcha-container” />

Second component’s container:

<div id=”recaptcha-container-resend” />

So that, the user may resend SMS verification several times more as long as RecaptchaVerifier does not believe that the user is a robot 🙂

Other Tips

Always use forms

See the screenshot below from my web application. The user interface is in Norwegian 🇳🇴 🙂

Screenshot 2019-06-16 at 17.49.23
Example User Interface for SMS Verification

We basically have one text box for the phone number and a submit button. So, this has to be implemented as a form, right? The picture below shows a simplified JSX code for this form:

Screenshot 2019-06-16 at 18.06.11

A good practice is to place the recaptcha-container at the bottom of the form. So that, there will be no confusing accessibility issues for the blind people. Also, we initialise the sign in process via this.handleSubmit call. This approach provides an advantage for desktop users, because handleSubmit will allow triggering the recaptcha check by pressing [ENTER] button while the focus is on phoneNumberInput element (<input … />). As a result of these benefits, always use forms while implementing Firebase SMS Verification interface.

Recaptcha window is not responsive

This is another unfortunate case with Firebase Recaptcha services. Captcha pictures presented inside the iframe have fixed width and critical recaptcha buttons become invisible and non-scrollable for the users with very small mobile screens (such as iPhone5). To fix this issue, I recommend using some media query on grecaptcha-badge CSS class. See the code below:

Screenshot 2019-06-16 at 18.16.29
Media query for 

The result is not perfect, but it keeps the iPhone 5 users in the game.

IMG_1793

Use libphonenumber-js for formatting

If you’d like to format the phone number inside the text box (<input className=”phoneNumberInput” … />), libphonenumber-js is a great utility. You can apply required country code settings by simply adding 3 lines of code into your application. You can learn more about AsYouType formatter by the URL below:

https://www.npmjs.com/package/libphonenumber-js

Credits to my colleague Iva Ivanova 👩‍🔧 on this final tip.

That’s all folks! See you next time with another challenge!

Sercan Leylek / OSLO

 

 

Advertisements

Using Cloud Firestore with React

Cloud Firestore is a NoSql database and this is my first time in Firebase world’s schema-less databases. This article should help to those who would like to get a grip on NoSql databases and who would also like to practice React programming further.

If you have no idea about NoSql databases, I recommend you to watch the video below:

What do we build in this tutorial?

Let’s have a vision of what we are actually developing here. The name of my application is show-cities-firebase and the whole source code is in my github repository. Besides, the app will have following features:

  • Connecting React app with Cloud Firestore database (Not Realtime Database)
  • Keep three attributes for each record
    • ID
    • City name
    • Population
  • List city names and corresponding population data
  • Sort the list by population
  • Delete specific city record
  • Delete all cities

Cloud Firestore Configuration

To start with, you need to include Firebase console access to your regular Google Account (same as gmail account). You may try to get it via https://console.firebase.google.com. And the same console address will help you follow your storage while we are working further. In other words, you will see your data collections under the console. See the GIF animation below to understand what I mean.

console_firebase_collections_example
Checking out Cloud Firestore Collections on console

The next thing you should do is to set up your config input. You must fill in the content regarding your account credentials. I keep this info inside my fire.js file.

Screen Shot 2019-04-22 at 11.57.45
fire.js

And I eventually import the configuration file inside my App.js:

import fire from './fire';

As you see in the picture above, you also need database.rules.json and firebase.json files. Add them to your project as I did in github repository. And we are ready to pull and push data.

Insert City Data

See how the constructor code looks like.

Screen Shot 2019-04-22 at 12.06.06

I keep the cities as an array inside of the state and the cities array contains the required data fields such as id, city and population. I think sortASC attribute’s task is apparent and I initialise the app with maxID = -1 value. Firebase databases do not provide auto-increment feature like in MySql or Oracle databases. Instead, you should do this manually. Therefore, I need maxID to auto-increment ID value for new city records. When the app starts, this value is updated with the highest ID. I call the function below on componentDidMount().

Screen Shot 2019-04-22 at 12.11.18

updateMaxID will return -1 unless there is some data in my collection. However, if there are earlier city records, it sorts the collections in descending order and picks the first top one thanks to the line below:

let maxIdItem = dbCollection.orderBy("id", "desc").limit(1);

After explaining how I set up my application state, let’s see how to insert some data into our collection. Take a look at my render code:

Screen Shot 2019-04-22 at 12.17.02

The application basically has two textboxes – city and population. I use required keyword for data validation, because I do not want any record either without a city name nor population. In addition to that, we have a tiny button which triggers this.addCity() on form submit.

Screen Shot 2019-04-22 at 19.27.03

This is the function where we implement the auto-increment of ID. I refer to this.state.maxID and increment it by 1. After inserting my new record into Cloud Firestore, I call this.updateMaxID().

You must have noticed that population and city ID values are parsed to integer before sending them into the database. This is necessary for sorting implementations and if you do not specify the type of the data, Firebase will store those values as String. Moreover, unlike relational databases, Firebase does not apply strict type rules. Therefore, one record may store the population value as String and while the next one stores it as integer. This is legal in NoSql world 🙂

In the last two lines of this.addCity(), I simply reset the textboxes with empty string. See the sample use below:

react_firebase_city_population_tutorial
Sample output
react_firebase_validation_required_example
Validation example

Listing records

Since we are able to insert some records into our collection, we had better list them as well. To do that, I wrote a function called this.loadCities() which pulls the data into application state.

Screen Shot 2019-04-22 at 20.03.32

The function above does not render the records. Therefore, I wrote another function which lists the city data and it also handles the sorting operations – this.createCitiesTable().

I will skip the implementation of other features. You may try to implement the rest on your own as a homework. If you get stuck, the github repository is always at your service.

Sercan Leylek / OSLO

Learning React – Vol.2

Last week, I went through the solutions of the first three tasks at tic-tac-toe game tutorial. This time, I will cover up the rest. Please see the list of tasks again:

  1. Display the location for each move in the format (col, row) in the move history list.
  2. Bold the currently selected item in the move list.
  3. Rewrite Board to use two loops to make the squares instead of hardcoding them.
  4. Add a toggle button that lets you sort the moves in either ascending or descending order.
  5. When someone wins, highlight the three squares that caused the win.
  6. When no one wins, display a message about the result being a draw.

If you’d like to take a look at the initial article, please check this one out.

Task #4 Add a toggle button to sort the moves

I must admit that I struggled with this task a bit, because I couldn’t make my mind whether I should reverse the history in this.state or in a copy of history array. After my first implementation, I realised that things get fuzzy when you mingle with the state quite often. Because, making changes in the state side-effects the other functions inside Game.js. So, I threw away my first code and followed a brand new plan.

To start with, we definitely need a new state attribute for the sorting choice. I added it to my constructor with default value ascending.

Screen Shot 2019-02-28 at 23.46.28.png
Add this.state.sortASC to the constructor of Game.js

 

We surely need a new function to toggle the sorting direction. This function will be called each time the user clicks on our sort button. So, I added toggleSort() inside Game component.

Screen Shot 2019-02-28 at 23.47.59.png
Add toggleSort() function

It is time to make some changes at rendering now. Since I do not want to reverse this.state.history, I get a copy of history and reverse it if sorting direction is descending. Also, please note that I also reverse the move value inside map(step, move).

Screen Shot 2019-02-28 at 23.52.44.png
Get a copy of history and reverse the copy

Next change inside the render creates our toggle button. I have been too lazy to add some SVG images and work on CSS. Therefore, I used UTF-8 arrows 🙂 And do you remember the toggleSort() function? This is a good time to use it.

Screen Shot 2019-02-28 at 23.55.33
Implement sortButton with an arrow

The last snippet is a piece of cake.

Screen Shot 2019-03-01 at 00.00.24
Add sortButton and use unordered list if you like

Ta taaa!!! Below is the outcome. If you’d like to see the commit, click here.

toggle sort tic-tac-toe react game
Tic-tac-toe game with sorting

Task #5 When someone wins, highlight the three squares that caused the win.

As we go further, the tasks become a bit more challenging. So, this implementation requires changes on all components. I will follow bottom to top approach. That means we will see the implementation sequence as following:

  1. Square.js
  2. Board.js
  3. Game.js

Square component is called by Board and it is responsible of rendering the boxes. Assume that Square.js receives an additional prop parameter which is boolean. And this input helps rendering the given box with gray background color or not. See the code below:

Screen Shot 2019-03-02 at 13.53.24
Add winnerSquare className if the boolean is true

And we certainly make this minor change inside index.css.

Screen Shot 2019-03-02 at 13.58.52.png
index.css

After these changes, we are done with the Square component. The next stop is Board. Let us first establish our previous assumption for the Square. Consider that renderSquare() function will pass the boolean to the Square.

Screen Shot 2019-03-02 at 14.00.53
renderSquare should get a second input: winnerSquare

And our createTheBoard() function still calls the previous function inside two for-loops. Assume that we have a handy function which figures out if the current square box is a winner box. So, call it accordingly.

Screen Shot 2019-03-02 at 14.05.18
this.isWinnerSquare(arrayPos)

And it is time to keep our promises again. Implement isWinnerSquare(). But see that we again make a new assumption here. Assume that Board will receive the winner coordinates from Game.js. If the coordinates are null, boolean is false. If current square box position is one of the winners, boolean is true. Simple huh?

“If you can’t write it down in English, you can’t code it.” – Peter Halpern

Screen Shot 2019-03-02 at 14.06.37
Implement isWinnerSquare(…)

We are about to finalise the implementation. calculateWinner(…) knows which lines are the winner squares. Instead of returning the name of the winner, it’d better start sending an object which keeps both the coordinates and the winner name.

Screen Shot 2019-03-02 at 14.12.29
calculateWinner will send the coordinates and the winner name.

As the final touch, I edited the use of winner object and the result is astonishing 🙂 See the commit here.

When someone wins, highlight the three squares that caused the win
When someone wins, highlight the three squares that caused the win.

Task #6 When no one wins, display a message about the result being a draw.

The last task is kind of easy. I see that the draw happens when all squares have some X or O value, but the calculateWinner function yet does not return a winner. So, I insert my check inside the if scope:

Screen Shot 2019-03-02 at 14.44.33
Game is a draw

If you are curious about the commit, check it here. And below is the final output of our tic-tac-toe game:

When no one wins, display a message about the result being a draw
Enhanced version of tic-tac-toe game

As you see, the winner of the last game is neither X or O, because the real winner is YOU who puts effort to learn React.

Sercan Leylek / OSLO

Learning React – Vol.1

Let me start the article with a cliché: Programming is learnt by practice. It is an oldie, but goodie. OK! I stop here. Two cliché for one article is more than enough.

Like many front-end developers, I also decided to take my chances with React and I wanted to push myself with some ambitious example where Firebase database and many other things involve, but after a while, I paused this project and aimed for some assisted tutorial.

At this point, I came across a tutorial on React’s official webpage. It is a tic-tac-toe game and the tutorial process goes quite smooth. The steps that you follow help you see the philosophy of React and shows you the way of doing things in a smart way.

Even though you only type what the mentor is asking you to do, this tutorial is still handy, because it gives you room to practice. And the exciting thing about the tic-tac-toe tutorial is the TO-DO list at the end of the lesson. These tasks encouraged me to enhance the game and I am currently down with the first three. See the full list of tasks below:

  1. Display the location for each move in the format (col, row) in the move history list.
  2. Bold the currently selected item in the move list.
  3. Rewrite Board to use two loops to make the squares instead of hardcoding them.
  4. Add a toggle button that lets you sort the moves in either ascending or descending order.
  5. When someone wins, highlight the three squares that caused the win.
  6. When no one wins, display a message about the result being a draw.

In this article, I assume that you have already followed the tutorial till the end and if you struggles with one of these tasks, I will share my solutions with you. Also, if you think my suggestion is not good enough, let me know how I can improve it.

Task #1 Display the location for each move in the history list.

As expected, we start with the simplest one. The challenging part here is to decide how column and row values should be stored and I hope you guess the answer already. Yes! We should create two new attributes inside this.state.history (Game.js). See the constructor below:

game-js-constructor
Adding row and col attributes

Certainly, that much is not enough. We should make some changes inside handleClick(…) as well. Each time a player clicks on the board, handleClick function is triggered. The changes below shows how we calculate the row and column values via array index.

calculate-row-and-column
Calculate row and column values

And we should also store the coordinate values for each move inside this.history.state. To do that, we make some modifications in history.concat(…).

store-row-and-column
Store the coordinates for each move

We are almost done. Currently, our tic-tac-toe game is able to save each move’s coordinates, but it doesn’t output to the user. Therefore, we will simply benefit those values inside the render.

output-render

That was it. If you’d like to check this commit, click here. And the gif below shows the current outcome.

Display the location for each move

Task #2 Bold the currently selected item in the move list.

Task number 2 challenged me a bit. It was actually easy to fix, but I didn’t feel peaceful after my first commit. I was sure that I should find my way through this.state.stepNumber, but my solution had some code duplication. See the first commit below:

Screen Shot 2019-02-23 at 20.22.56
My first commit for Task #2

As you see above, I compare the current move index with the stepNumber and add some CSS class inside the render. (selectedMove = fontWeight: bold) I apparently didn’t know what to do with the second <li> block. Also, this commit caused showing bold text on latest move as well. That wasn’t what I was expected to do. I should’ve shown the last clicked button with bold text, not the latest one all the time. See the result gif of the first commit:

Bold the currently selected item
The result of first commit

I got a better idea on the next day. Why not using a variable for the className? And also ignoring the CSS where history.length equals the current move number? I reorganised the code accordingly. See the commit here:

Screen Shot 2019-02-23 at 20.31.27
Task #2 – Improved solution

And the output is nicer 🙂 Now the move becomes bold only when the user clicks on it and the code has no redundant duplications.

Bold the currently selected item - improved

Task #3 Rewrite Board to use two loops …

To solve this problem, I needed to get some help from Google, because I didn’t know how to return html code from a function. Let us remember how our Board.js rendering was implemented:

Screen Shot 2019-02-23 at 20.36.56
Rendering on Board.js

Apparently, the code snippet above does not promise any flexibility and it is a trap for typos. (It happened to me 🙂 See it here)

So, we clearly need a function inside Board.js to help render look tidy. Therefore, I wrote a new function called createTheBoard(). We go through the rows and columns to render the squares and at the end, an array of html content is returned. See the last commit here.

Screen Shot 2019-02-23 at 20.40.56
Shorter render means longer life 🙂

Conclusion

I highly recommend to start with the default tutorial page of React. For example, learning that “this.state should be considered as private to a React component that it’s defined in” was a huge enlightenment for me.

Tic-tac-toe tutorial will help you understand fundamental concepts of React world and it also gives you room for improvement. I will hopefully solve the following tasks (#4, #5, #6) soon and post it. Until then, ha det bra!

Sercan Leylek / OSLO

PHP 7 Migration Challenges and Fix Tips

Php 7 Migration is still a hot issue for developers around the globe. Some host providers already completed the process, but many others are still lacking behind. Therefore, it is good to share some wisdom and technical tips that will help random PHP citizens around the world.

I see two major parameters that should be carefully considered in the beginning of this tough marathon and they are reusability + versatility.

Reusability

Everyone should agree the equation below:

Reusability = Time = Cost

We all wrote our PHP 5.0 code some time ago. Our frontend applications are built on top of it and those PHP programs worked fine in the dungeons of our CMS. Now, we have to change the architecture of the underground facilities, but remember! The old code provided the expected results and all we want is to keep it the same. Because, the old code is reliable and well-testet over time. Integrating the failing parts to the newer version of PHP is sufficient. As a result of these, we don’t aim for rewriting of classes, we aim for catching and fixing the integration issues. This is a search & destroy mission. Although this strategy failed in Vietnam War, but never mind.

Search & Destroy mission php 7

Versatility

This will be a long process for most of the developers and since you are working in short sprint cycles (say 3 weeks), at least half of your migration commits will be delivered to the production server which still runs on PHP 5.0. One may disagree with this approach by saying:

‘Nope, we will keep the migration commits on a different git branch and when all tests are complete and sufficient code coverage is reached, we will merge these two branches.’

The decision is certainly up to you, but I wouldn’t recommend this method. Because, there will be surely some conflicts after this big merge operation and the outcome will not be as reliable as you think. Therefore, I recommend to follow another path: Make sure that your fix commits works both on PHP 7.0 and PHP 5.0.

Do not merge your branches at the end of the process like Moses did

Fatal Error Examples and Solution Tips

EXP-1: “Fatal error: Uncaught ArgumentCountError: Too few arguments to function…”

We start with a popular one. You will see this error message when one of your php functions is using a default argument. See the example function below:

public function myFunction($array1, $array2) {
    if (!$array2) {
        $array2 = array();
    }
    return count($array1) + count($array2);
}

The simple php function above expects two arrays as arguments and it returns the sum of array sizes. myFunction will work fine on PHP 5 even though you pass only one array, but the same call will give a fatal error message on PHP 7. Because, PHP 7 does not automatically assign a relevant default value on undefined arguments like PHP 5 does. Therefore, we should edit the function as following:

public function myFunction($array1, $array2 = array()) {
    if (!$array2) {
        $array2 = array();
    }
    return count($array1) + count($array2);
}

By assigning an empty array to the second argument, we let the function run both on PHP 5 and PHP 7.0. The same error message will occur when the second argument is a string, integer or an object. Then, we should use the relevant default value in syntax. For example, empty string “”, 0 or NULL values can be used accordingly for default initialisation.

You may end up getting the same error on redundant argument declaration. For example, $array2 might be declared in the function signature, but it might be actually never used. Certainly, this is the simplest case. Just delete the redundant argument and get over with the refactoring.

EXP-2: “Deprecated Methods with the same name as their class will not be constructors in a future version.”

The error message above already explains a lot, but seeing an example code excerpt is definitely enlightening:

class CafPage extends myPage {
    function CafPage($tid, $view_id, $title, $site) {
        $this->myPage($tid, $view_id, $title, $site);
    }
}

The error apparently triggers in the constructor. PHP 7 does not like using the same name on both the class and the constructor function. Therefore, the same function should be edited as following:

class CafPage extends myPage {
    function __construct($tid, $view_id, $title, $site) {
        $this->myPage($tid, $view_id, $title, $site);
    }
}

This fix will run on PHP 5 and 7 without any issues. Remember: Versatility!

bruce lee gif php 7

EXP-3: “Non-static method … should not be called statically in …”

I witnessed this error message in a function call similar to the one below:

return UserdataHelper::runTemplate('bla-bla.php');

It seems PHP 7 was not happy with :: reference on non-static methods. Therefore, I firstly initiated the caller object and triggered the runTemplate function by arrow object operator (->).

return (new UserdataHelper)->runTemplate('bla-bla.php');

And Eureka! It works!

Conclusion

Three example error messages are handled in this post. These are the frequent error types that I came across during our migration process. Above all, the sneakiest php errors are those which do not output a fatal error message. These issues usually occur when an ajax call refers to a php function and they are harder to find out. So, most secure testing method is of course validating the expected functionality of your web-application.

Sercan Leylek / OSLO

Solving obscure keyboard fail in Cordova

I’ve been working on a SPA which is built in Node.js and since, my team does not deliver products in native app programming, we use Cordova Apache to build the same product as an iOS app. This approach certainly helps us gain in time, but some deep problems are more difficult to handle. Because, one cannot edit constraints through Cordova platform and hence, some parts of the application remain as black-box for us. Such disadvantage causes trouble when we are not sure about the diagnosis of a defect. Just like the error log below:

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2018-10-16 15:24:25.691893+0200 Unibok[70880:8601663] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"",
"",
"",
"<NSLayoutConstraint:0x600003509130 'UIButtonBar.maximumAlignmentSize' _UIButtonBarButton:0x7f861b9324d0.height == UILayoutGuide:0x600002f05c00'UIViewLayoutMarginsGuide'.height   (active)>",
"<NSLayoutConstraint:0x600003542850 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600002f05c00'UIViewLayoutMarginsGuide']-(9)-|   (active, names: '|':_UIButtonBarStackView:0x7f861b948b10 )>",
"<NSLayoutConstraint:0x600003543070 'UIView-topMargin-guide-constraint' V:|-(10)-[UILayoutGuide:0x600002f05c00'UIViewLayoutMarginsGuide']   (active, names: '|':_UIButtonBarStackView:0x7f861b948b10 )>"
)

Because of the failure above, the keyboard on iPhone or iPad was not usable. Whenever the user touched on a textbox item (<-input->), the application actually triggered the keyboard interface, but the fail above conflicts some constraints and it crashed the keyboard. That was all about the fail.

I spent enough time thinking if this issue was related to some keyboard plugin like many people recommended. (ionic-plugin-keyboard vs. cordova-plugin-keyboard) But the solution was simpler than I thought and our implementation was more innocent than I doubted 🙂

SOLUTION

Recent radar ticket below opened the doors of clarification for me.

https://openradar.appspot.com/radar?id=5018321736957952

As Brent Dearth mentions in the comment, the entire defect was related to a fail in iOS 12.0. And the workaround is to remove your viewport-fit meta tag. The bold text shows the troubled code in my case:

<meta name="viewport" content="maximum-scale=1.0, initial-scale=1.0, user-scalable=no, viewport-fit=cover">

After removing the viewport-fit flag, the app worked on all iOS devices perfectly.

Sercan Leylek / OSLO

P.s. Thanks to Darryl Pogue on solving the issue here.

Angular 6 unexpectedly redirects in Safari

This has been a challenging issue that I came across this week. My web application is simply supposed to load some dynamic content after some button is clicked. It actually works fine on Chrome, Firefox and yes even on IE11. 🙂 However, the same app failed on Safari both on desktop and iOS. It was actually still loading the requested content, but was redirecting to the previous page instead of showing the content.

Safari inspect window showed no single error or warning, but Chrome inspection demonstrated the warning message below:

Form submission canceled because the form is not connected
Form submission canceled because the form is not connected

Solution!!!

This warning encouraged me to re-evaluate the click event of the angular component. So, I noticed that my button was lacking type=”button” attribute. After inserting the lacking attribute, Safari stopped redundant redirection of the page and the warning message on Chrome disappeared. Just another happy ending!

type button angular safari page redirection.png

Sercan Leylek / OSLO

How to ignore git commit errors?

I recently work with some 3rd party code and ran into an annoying failure which totally blocks me from committing my changes via git. I get a failure message “A number of errors found, aborting commit.”. And the screenshot looks like the picture below:

errors found, aborting commit

I understand that git is smart and it is persuading the developers to write –and commit– more responsible code. All these errors are simple fixes, but I have no time to go through someone else’s error pile. Plus, I know that the code is working.

So, how can I ignore git’s highbrow attitude and go around the issue?

SOLUTION

You need to include a magic keyword while you are committing. ‘–no-verify‘ will just ignore git’s list of errors and do the trick for you. See the example command:

git commit -m "Mannen og Muren rocks!!!" --no-verify

Sercan Leylek

Chrome vs. macOS Sierra Struggle

I recently upgraded my Mac to the version 10.13.1 and ended up with a weird error on my primary development tool that is certainly the most popular browser, Chrome.

Because of my work, I use postgres database and a local host which utilises https protocol. After the macOS Sierra upgrade, I had the following (and annoying) error which blocked my access to my local server.

main-qimg-b0bc2a8995fbfefeb5764fd3a3f33e4c

However, the message I received did not contain a “proceed to” link. Therefore, I couldn’t access my local host as I always did.

I emptied the web cache, reset the application cache, deleted the service worker storage and tried the basic recommendations of Google (such as deleting the browsing history, etc…). None of them helped. On the other hand, my Safari browser was able to access the local host. So, there was no problem with my service, the issue was on Chrome’s communication with macOS Sierra 10.13.1.

Solution

Luckily, starting Chrome on unsafe mode proved my theory correct. Use the command below and bypass the issue.

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome –ignore-certificate-errors &> /dev/null &

Conclusion

My solution is unfortunately a temporary one. I didn’t want to waste more time by downgrading the macOS Sierra version. I hope the version 10.13.2 will fix it or maybe the newer version of Chrome will handle this buggy situation.

I experienced a similar situation on autoPlay functionality. Safari decided to block autoplay of video and sound objects, however Chrome will do the same on its January 2018 release. As a result, this experience has been another case where Safari is faster at implementing new features, but their web development tools cannot offer the quality of Chrome, yet.

Sercan Leylek / OSLO

 

Nordic.js > Day 2

Like all the good things, Nordic.js also came to an end – for now. Just like yesterday, I am going to write down the parts that fully got my attention during the day.

Claudia Hernandez: JS in Wonderland

This presentation made most people see a side of javascript that never thought before. Claudia Hernandez introduced the web-page JSFuck and before that, she showed us a js expression similar to the one below:

![]

When you give the above characters to your js console, what do you think the result will be? Let’s read it from right to left.

  1. [] represents an empty array.
  2. If you negate an empty array which is received as a true value by exclamation mark, the result will be false.

So, can you guess the value true? It shouldn’t be hard to guess:

!![] = true
!![] = true
As you may already guess, JSFuck approach abuses the quirks in javascript. In a more positive way, we may call this approach as the art of javascript coding by using only non-alphanumerical characters.

In the beginning of Hernandez’ presentation, all the effort looked like some meaningless puzzle game – and I guess that is also what she wants the audience to think in the early minutes of her presentation. But, this technique actually led to the discovery of a serious hack. Here is a quote from the talk:

jsfuck hack storks nest sercan leylek hernandez

So, some people actually managed to inject some javascript code by using JSFuck way of programming. That was unexpected! And Hernandez perfectly underlines the whole idea with her remarkable ending.

That’s the point about the science. We should keep on discovering by pushing the limits even though there is no practical use in short run.

And another valuable quote from her presentation:

if hemingway wrote javascript

Feross Aboukhadijeh: P2P

Here is another hard-to-forget presentation from this year’s Nordic.js. I think Feross Aboukhadijeh presented the most interactive speech of the conference with his talk about Internet’s itself and P2P technology. He firstly shared a quite clear view of what attributes should internet possess:

  1. Resilient
  2. No middlemen
  3. Diverse
  4. People Powered

But, is it really resilient, diverse and etc?

Feross Aboukhadijeh p2p nordicjs

Feross shows that utopian internet model and modern reality do not really map. Internet is built to be a communication system to help its peers find an alternative way at the times of unavailabilities, but service giants stand in the centre of peers.

  • If they fail, we all fail. (Resilience?)
  • If they decide to halt a service, we have no right to speak up. (No middlemen?)
  • If they are blocked in some country, we are also blocked. (Diverse & People Powered. I’d like to remind you that Wikipedia is still blocked in Turkey.)

I felt huge sympathy for the thoughts of Feross, because that is some idea that I’ve been working on for some time via my product Reservation.no which recently declared war to the giants in table booking system.

Feross also caused us see that URL is actually a bad thing 🙂

The L letter in URL stands for location. And if what you are looking for isn’t there, you will simply get a 404 error, although it is somewhere in the web.

That makes me think: Could or should URL be replaced in the future?

Ben Schwarz: Beyond the bubble

One cannot always give compliments to an event, right? Otherwise, there would be no point to improve things. The presentation of Ben Schwarz, ‘Beyond the bubble’, of course handled a critical accessibility issue. The founder of calibreapp, tutored us about the performance issues caused by the ignorance of developers and his stats also represented the status of internet accessibility for the majority of the world. However, most of these points were actually described with a more informative tone by Scott Jehl in Responsible Responsive Design (Chapter 4: Delivering Responsibly).

Despite my critical views, ‘Beyond the bubble’ still hits the target. The participants of the event will be more careful when they include their CSS/JS files from now on and many of them will behave more professionally at performance testing.

Final Comments

I regret that I am not able to mention the other speakers’ hard work, but I am sure that some other blogger/developer is writing about them. Big thanks to all speakers!

Also, I have a feeling that the second day of Nordic.js was more fun. Maybe that was because of the distributed performances of the hosts, Unn Swanström & Mattias P. Johansson. (Like live tattoo show, video call, etc…)

And, special thanks to the conference organisers: Jonny Strömberg, Martina Elm and Johannes Edelstam.

Screen Shot 2017-09-08 at 23.57.28

See you all next year!

Sercan Leylek / Stockholm