Tag Archives: JavaScript

VOIP

VOIP In Matrix JS SDK

This module outlines how two users in a room can set up a Voice over IP (VoIP) call to each other. Voice and video calls are built upon the WebRTC 1.0 standard. Call signalling is achieved by sending message events to the room. In this version of the spec, only two-party communication is supported (e.g. between two peers, or between a peer and a multi-point conferencing unit). This means that clients MUST only send call events to rooms with exactly two participants.

For a complete overview of Matrix Javascript SDK configuration, please go to our Matrix Javascript SDK.

Matrix Javascript SDK

Establish a call

This method is call by the caller when they wish to establish a call.

matrixCall = matrixcs.createNewMatrixCall(
        MATRIX_CLIENT_OBJ, ROOM_ID
);

For voice call

matrixCall.placeVoiceCall();
matrixCall.setRemoteAudioElement(document.getElementById("remote-audio"));

For video call

matrixCall.placeVideoCall(
    document.getElementById("remote-video"),
    document.getElementById("local-video")
);

Incoming call event for callee

client.on("Call.incoming", function(c) {
    console.log("Call ringing");
    console.log("Incoming call");
});

Callee answer the call

This method is call by the callee when they wish to answer the call.

call.answer();

Hangup the call

Method call by either party to signal their termination of the call. This can be sent either once the call has has been established or before to abort the call.

call.hangup();

Examples

<html>
<head>
<title>VoIP Test</title>
http://lib/matrix.js
http://call.js
</head>
<body>
	You can place and receive calls with this example. Make sure to edit the
    constants in <code>call.js</code> first.
    <div id="config"></div>
    <div id="result"></div>
    <button id="call">Place Call</button>
    <button id="answer">Answer Call</button>
    <button id="hangup">Hangup Call</button>
    <div id="videoBackground">
        <div id="videoContainer">
            <video id="remote"></video>
        </div>
    </div>
    <div id="videoBackground">
        <div id="videoContainer">
            <video id="local"></video>
        </div>
    </div>
</body>
</html>
console.log("Loading browser sdk");
var BASE_URL = "https://matrix.org";
var TOKEN = "accesstokengoeshere";
var USER_ID = "@username:localhost";
var ROOM_ID = "!room:id";


var client = matrixcs.createClient({
    baseUrl: BASE_URL,
    accessToken: TOKEN,
    userId: USER_ID
});
var call;

function disableButtons(place, answer, hangup) {
    document.getElementById("hangup").disabled = hangup;
    document.getElementById("answer").disabled = answer;
    document.getElementById("call").disabled = place;
}

function addListeners(call) {
    var lastError = "";
    call.on("hangup", function() {
        disableButtons(false, true, true);
        document.getElementById("result").innerHTML = (
            "<p>Call ended. Last error: "+lastError+"</p>"
        );
    });
    call.on("error", function(err) {
        lastError = err.message;
        call.hangup();
        disableButtons(false, true, true);
    });
}

window.onload = function() {
    document.getElementById("result").innerHTML = "<p>Please wait. Syncing...</p>";
    document.getElementById("config").innerHTML = "<p>" +
        "Homeserver: <code>"+BASE_URL+"</code><br/>"+
        "Room: <code>"+ROOM_ID+"</code><br/>"+
        "User: <code>"+USER_ID+"</code><br/>"+
        "</p>";
    disableButtons(true, true, true);
};

client.on("sync", function(state, prevState, data) {
    switch (state) {
        case "PREPARED":
          syncComplete();
        break;
   }
});

function syncComplete() {
    document.getElementById("result").innerHTML = "<p>Ready for calls.</p>";
    disableButtons(false, true, true);

    document.getElementById("call").onclick = function() {
        console.log("Placing call...");
        call = matrixcs.createNewMatrixCall(
            client, ROOM_ID
        );
        console.log("Call => %s", call);
        addListeners(call);
        call.placeVideoCall(
            document.getElementById("remote"),
            document.getElementById("local")
        );
        document.getElementById("result").innerHTML = "<p>Placed call.</p>";
        disableButtons(true, true, false);
    };

    document.getElementById("hangup").onclick = function() {
        console.log("Hanging up call...");
        console.log("Call => %s", call);
        call.hangup();
        document.getElementById("result").innerHTML = "<p>Hungup call.</p>";
    };

    document.getElementById("answer").onclick = function() {
        console.log("Answering call...");
        console.log("Call => %s", call);
        call.answer();
        disableButtons(true, true, false);
        document.getElementById("result").innerHTML = "<p>Answered call.</p>";
    };

    client.on("Call.incoming", function(c) {
        console.log("Call ringing");
        disableButtons(true, false, false);
        document.getElementById("result").innerHTML = "<p>Incoming call...</p>";
        call = c;
        addListeners(call);
    });
}
client.startClient();

 

Matrix Javascript SDK

Matrix Client-Server r0 SDK for JavaScript. This SDK can be run in a browser or in Node.js.

Quickstart

In a browser

Download either the full or minified version from https://github.com/matrix-org/matrix-js-sdk/releases/latest and add that as a <script> to your page. There will be a global variable matrixcs attached to window through which you can access the SDK. See below for how to include libolm to enable end-to-end-encryption.

Please check the working browser example for more information.

In Node.js

Ensure you have the latest LTS version of Node.js installed.

Using yarn instead of npm is recommended. Please see the Yarn install guide if you do not have it already.

yarn add matrix-js-sdk

var sdk = require("matrix-js-sdk");
var client = sdk.createClient("https://matrix.org");
client.publicRooms(function(err, data) {
    console.log("Public Rooms: %s", JSON.stringify(data));
});

See below for how to include libolm to enable end-to-end-encryption. Please check the Node.js terminal app for a more complex example.

To start the client:

await client.startClient({initialSyncLimit: 10});

You can perform a call to /sync to get the current state of the client:

client.once('sync', function(state, prevState, res) {
    if(state === 'PREPARED') {
        console.log("prepared");
    } else {
        console.log(state);
        process.exit(1);
    }
});

To send a message:

var content = {
    "body": "message text",
    "msgtype": "m.text"
};
client.sendEvent("roomId", "m.room.message", content, "", (err, res) => {
    console.log(err);
});

To listen for message events:

client.on("Room.timeline", function(event, room, toStartOfTimeline) {
  if (event.getType() !== "m.room.message") {
    return; // only use messages
  }
  console.log(event.event.content.body);
});

By default, the matrix-js-sdk client uses the MemoryStore to store events as they are received. For example to iterate through the currently stored timeline for a room:

Object.keys(client.store.rooms).forEach((roomId) => {
  client.getRoom(roomId).timeline.forEach(t => {
      console.log(t.event);
  });
});

What does this SDK do?

This SDK provides a full object model around the Matrix Client-Server API and emits events for incoming data and state changes. Aside from wrapping the HTTP API, it:

  • Handles syncing (via /initialSync and /events)
  • Handles the generation of “friendly” room and member names.
  • Handles historical RoomMember information (e.g. display names).
  • Manages room member state across multiple events (e.g. it handles typing, power levels and membership changes).
  • Exposes high-level objects like Rooms, RoomState, RoomMembers and Users which can be listened to for things like name changes, new messages, membership changes, presence changes, and more.
  • Handle “local echo” of messages sent using the SDK. This means that messages that have just been sent will appear in the timeline as ‘sending’, until it completes. This is beneficial because it prevents there being a gap between hitting the send button and having the “remote echo” arrive.
  • Mark messages which failed to send as not sent.
  • Automatically retry requests to send messages due to network errors.
  • Automatically retry requests to send messages due to rate limiting errors.
  • Handle queueing of messages.
  • Handles pagination.
  • Handle assigning push actions for events.
  • Handles room initial sync on accepting invites.
  • Handles WebRTC calling.

Later versions of the SDK will:

  • Expose a RoomSummary which would be suitable for a recents page.
  • Provide different pluggable storage layers (e.g. local storage, database-backed)

 Usage

 Conventions

 Emitted events

The SDK will emit events using an EventEmitter. It also emits object models (e.g. Rooms, RoomMembers) when they are updated.

// Listen for low-level MatrixEvents
client.on("event", function(event) {
    console.log(event.getType());
});

// Listen for typing changes
client.on("RoomMember.typing", function(event, member) {
    if (member.typing) {
      console.log(member.name + " is typing...");
    }
    else {
      console.log(member.name + " stopped typing.");
    }
});

// start the client to setup the connection to the server
client.startClient();

Promises and Callbacks

Most of the methods in the SDK are asynchronous: they do not directly return a result, but instead return a Promise which will be fulfilled in the future.

The typical usage is something like:

matrixClient.someMethod(arg1, arg2).done(function(result) {
    ...
});

Alternatively, if you have a Node.js-style callback(err, result) function, you can pass the result of the promise into it with something like:

matrixClient.someMethod(arg1, arg2).nodeify(callback);

The main thing to note is that it is an error to discard the result of a promise-returning function, as that will cause exceptions to go unobserved. If you have nothing better to do with the result, just call .done() on it. See http://documentup.com/kriskowal/q/#the-end for more information.

Methods which return a promise show this in their documentation.

Many methods in the SDK support both Node.js-style callbacks and Promises, via an optional callback argument. The callback support is now deprecated: new methods do not include a callback argument, and in the future it may be removed from existing methods.

Examples

This section provides some useful code snippets which demonstrate the core functionality of the SDK. These examples assume the SDK is setup like this:

var sdk = require("matrix-js-sdk");
var myUserId = "@example:localhost";
var myAccessToken = "QGV4YW1wbGU6bG9jYWxob3N0.qPEvLuYfNBjxikiCjP";
var matrixClient = sdk.createClient({
    baseUrl: "http://localhost:8008",
    accessToken: myAccessToken,
    userId: myUserId
});

Automatically join rooms when invited

matrixClient.on("RoomMember.membership", function(event, member) {
    if (member.membership === "invite" && member.userId === myUserId) {
        matrixClient.joinRoom(member.roomId).done(function() {
           console.log("Auto-joined %s", member.roomId);
        });
    }
});

matrixClient.startClient();

Print out messages for all rooms

matrixClient.on("Room.timeline", function(event, room, toStartOfTimeline) {
    if (toStartOfTimeline) {
        return; // don't print paginated results
    }
    if (event.getType() !== "m.room.message") {
        return; // only print messages
    }
    console.log(
        // the room name will update with m.room.name events automatically
        "(%s) %s :: %s", room.name, event.getSender(), event.getContent().body
    );
});

matrixClient.startClient();

Output:

(My Room) @megan:localhost :: Hello world
(My Room) @megan:localhost :: how are you?
(My Room) @example:localhost :: I am good
(My Room) @example:localhost :: change the room name
(My New Room) @megan:localhost :: done

Print out membership lists whenever they are changed

matrixClient.on("RoomState.members", function(event, state, member) {
    var room = matrixClient.getRoom(state.roomId);
    if (!room) {
       return;
    }
    var memberList = state.getMembers();
    console.log(room.name);
    console.log(Array(room.name.length + 1).join("="));  // underline
    for (var i = 0; i < memberList.length; i++) {
       console.log(
       "(%s) %s",
           memberList[i].membership,
           memberList[i].name
       );
    }
});

matrixClient.startClient();

Output:

My Room
=======
(join) @example:localhost
(leave) @alice:localhost
(join) Bob
(invite) @charlie:localhost

API Reference

A hosted reference can be found at http://matrix-org.github.io/matrix-js-sdk/index.html

This SDK uses JSDoc3 style comments. You can manually build and host the API reference from the source files like this:

$ yarn gendoc
$ cd .jsdoc
$ python -m SimpleHTTPServer 8005

Then visit http://localhost:8005 to see the API docs.

End-to-end encryption support

The SDK supports end-to-end encryption via the Olm and Megolm protocols, using libolm. It is left up to the application to make libolm available, via the Olm global.

It is also necessry to call matrixClient.initCrypto() after creating a new MatrixClient (but before calling matrixClient.startClient()) to initialise the crypto layer.

If the Olm global is not available, the SDK will show a warning, as shown below; initCrypto() will also fail.

Unable to load crypto module: crypto will be disabled: Error: global.Olm is not defined

If the crypto layer is not (successfully) initialised, the SDK will continue to work for unencrypted rooms, but it will not support the E2E parts of the Matrix specification.

To provide the Olm library in a browser application:

To provide the Olm library in a node.js application:

  • yarn add https://packages.matrix.org/npm/olm/olm-3.0.0.tgz (replace the URL with the latest version you want to use from https://packages.matrix.org/npm/olm/)
  • global.Olm = require('olm'); before loading matrix-js-sdk.

If you want to package Olm as dependency for your node.js application, you can use yarn add https://packages.matrix.org/npm/olm/olm-3.0.0.tgz. If your application also works without e2e crypto enabled, add --optional to mark it as an optional dependency.

Contributing

This section is for people who want to modify the SDK. If you just want to use this SDK, skip this section.

First, you need to pull in the right build tools:

$ yarn install

Building

To build a browser version from scratch when developing::

$ yarn build

To constantly do builds when files are modified (using watchify)::

$ yarn watch

To run tests (Jasmine)::

$ yarn test

To run linting:

$ yarn lint

Country Picker With Flag jQuery plugin

About single/multiple country picker jQuery plugin :-

This single/multiple country picker jQuery plugin allows you to easily display a list of countries with flag in your Bootstrap form.

Dependencies :-

Usage :-

Create your <select> with the .country_selector class and add option of required countries.

Improtant Notes:
For multiple country picker add multiple attribute in <select> tag.

<select class="country_selector">
   <option value="">Select a country...</option>
   <option value="AF">Afghanistan</option>
   <option value="AX">Åland Islands</option>
   <option value="AL">Albania</option>
   <option value="DZ">Algeria</option>
   <option value="AS">American Samoa</option>
   <option value="AD">Andorra</option>
   <option value="AO">Angola</option>
   <option value="AI">Anguilla</option>
   <option value="AQ">Antarctica</option>
   <option value="AG">Antigua and Barbuda</option>
   <option value="AR">Argentina</option>
   <option value="AM">Armenia</option>
   <option value="AW">Aruba</option>
   <option value="AU">Australia</option>
   <option value="AT">Austria</option>
   <option value="AZ">Azerbaijan</option>
   <option value="BS">Bahamas</option>
   <option value="BH">Bahrain</option>
   <option value="BD">Bangladesh</option>
   <option value="BB">Barbados</option>
   <option value="BY">Belarus</option>
   <option value="BE">Belgium</option>
   <option value="BZ">Belize</option>
   <option value="BJ">Benin</option>
   <option value="BM">Bermuda</option>
   <option value="BT">Bhutan</option>
   <option value="BO">Bolivia, Plurinational State of</option>
   <option value="BA">Bosnia and Herzegovina</option>
   <option value="BW">Botswana</option>
   <option value="BV">Bouvet Island</option>
   <option value="BR">Brazil</option>
   <option value="IO">British Indian Ocean Territory</option>
   <option value="BN">Brunei Darussalam</option>
   <option value="BG">Bulgaria</option>
   <option value="BF">Burkina Faso</option>
   <option value="BI">Burundi</option>
   <option value="KH">Cambodia</option>
   <option value="CM">Cameroon</option>
   <option value="CA">Canada</option>
   <option value="CV">Cape Verde</option>
   <option value="KY">Cayman Islands</option>
   <option value="CF">Central African Republic</option>
   <option value="TD">Chad</option>
   <option value="CL">Chile</option>
   <option value="CN">China</option>
   <option value="CX">Christmas Island</option>
   <option value="CC">Cocos (Keeling) Islands</option>
   <option value="CO">Colombia</option>
   <option value="KM">Comoros</option>
   <option value="CG">Congo</option>
   <option value="CD">Congo, the Democratic Republic of the</option>
   <option value="CK">Cook Islands</option>
   <option value="CR">Costa Rica</option>
   <option value="CI">Côte d\'Ivoire</option>
   <option value="HR">Croatia</option>
   <option value="CU">Cuba</option>
   <option value="CY">Cyprus</option>
   <option value="CZ">Czech Republic</option>
   <option value="DK">Denmark</option>
   <option value="DJ">Djibouti</option>
   <option value="DM">Dominica</option>
   <option value="DO">Dominican Republic</option>
   <option value="EC">Ecuador</option>
   <option value="EG">Egypt</option>
   <option value="SV">El Salvador</option>
   <option value="GQ">Equatorial Guinea</option>
   <option value="ER">Eritrea</option>
   <option value="EE">Estonia</option>
   <option value="ET">Ethiopia</option>
   <option value="FK">Falkland Islands (Malvinas)</option>
   <option value="FO">Faroe Islands</option>
   <option value="FJ">Fiji</option>
   <option value="FI">Finland</option>
   <option value="FR">France</option>
   <option value="GF">French Guiana</option>
   <option value="PF">French Polynesia</option>
   <option value="TF">French Southern Territories</option>
   <option value="GA">Gabon</option>
   <option value="GM">Gambia</option>
   <option value="GE">Georgia</option>
   <option value="DE">Germany</option>
   <option value="GH">Ghana</option>
   <option value="GI">Gibraltar</option>
   <option value="GR">Greece</option>
   <option value="GL">Greenland</option>
   <option value="GD">Grenada</option>
   <option value="GP">Guadeloupe</option>
   <option value="GU">Guam</option>
   <option value="GT">Guatemala</option>
   <option value="GG">Guernsey</option>
   <option value="GN">Guinea</option>
   <option value="GW">Guinea-Bissau</option>
   <option value="GY">Guyana</option>
   <option value="HT">Haiti</option>
   <option value="HM">Heard Island and McDonald Islands</option>
   <option value="VA">Holy See (Vatican City State)</option>
   <option value="HN">Honduras</option>
   <option value="HK">Hong Kong</option>
   <option value="HU">Hungary</option>
   <option value="IS">Iceland</option>
   <option value="IN">India</option>
   <option value="ID">Indonesia</option>
   <option value="IR">Iran, Islamic Republic of</option>
   <option value="IQ">Iraq</option>
   <option value="IE">Ireland</option>
   <option value="IM">Isle of Man</option>
   <option value="IL">Israel</option>
   <option value="IT">Italy</option>
   <option value="JM">Jamaica</option>
   <option value="JP">Japan</option>
   <option value="JE">Jersey</option>
   <option value="JO">Jordan</option>
   <option value="KZ">Kazakhstan</option>
   <option value="KE">Kenya</option>
   <option value="KI">Kiribati</option>
   <option value="KP">Korea, Democratic People\'s Republic of</option>
   <option value="KR">Korea, Republic of</option>
   <option value="KW">Kuwait</option>
   <option value="KG">Kyrgyzstan</option>
   <option value="LA">Lao People\'s Democratic Republic</option>
   <option value="LV">Latvia</option>
   <option value="LB">Lebanon</option>
   <option value="LS">Lesotho</option>
   <option value="LR">Liberia</option>
   <option value="LY">Libyan Arab Jamahiriya</option>
   <option value="LI">Liechtenstein</option>
   <option value="LT">Lithuania</option>
   <option value="LU">Luxembourg</option>
   <option value="MO">Macao</option>
   <option value="MK">Macedonia, the former Yugoslav Republic of</option>
   <option value="MG">Madagascar</option>
   <option value="MW">Malawi</option>
   <option value="MY">Malaysia</option>
   <option value="MV">Maldives</option>
   <option value="ML">Mali</option>
   <option value="MT">Malta</option>
   <option value="MH">Marshall Islands</option>
   <option value="MQ">Martinique</option>
   <option value="MR">Mauritania</option>
   <option value="MU">Mauritius</option>
   <option value="YT">Mayotte</option>
   <option value="MX">Mexico</option>
   <option value="FM">Micronesia, Federated States of</option>
   <option value="MD">Moldova, Republic of</option>
   <option value="MC">Monaco</option>
   <option value="MN">Mongolia</option>
   <option value="ME">Montenegro</option>
   <option value="MS">Montserrat</option>
   <option value="MA">Morocco</option>
   <option value="MZ">Mozambique</option>
   <option value="MM">Myanmar</option>
   <option value="NA">Namibia</option>
   <option value="NR">Nauru</option>
   <option value="NP">Nepal</option>
   <option value="NL">Netherlands</option>
   <option value="AN">Netherlands Antilles</option>
   <option value="NC">New Caledonia</option>
   <option value="NZ">New Zealand</option>
   <option value="NI">Nicaragua</option>
   <option value="NE">Niger</option>
   <option value="NG">Nigeria</option>
   <option value="NU">Niue</option>
   <option value="NF">Norfolk Island</option>
   <option value="MP">Northern Mariana Islands</option>
   <option value="NO">Norway</option>
   <option value="OM">Oman</option>
   <option value="PK">Pakistan</option>
   <option value="PW">Palau</option>
   <option value="PS">Palestinian Territory, Occupied</option>
   <option value="PA">Panama</option>
   <option value="PG">Papua New Guinea</option>
   <option value="PY">Paraguay</option>
   <option value="PE">Peru</option>
   <option value="PH">Philippines</option>
   <option value="PN">Pitcairn</option>
   <option value="PL">Poland</option>
   <option value="PT">Portugal</option>
   <option value="PR">Puerto Rico</option>
   <option value="QA">Qatar</option>
   <option value="RE">Réunion</option>
   <option value="RO">Romania</option>
   <option value="RU">Russian Federation</option>
   <option value="RW">Rwanda</option>
   <option value="BL">Saint Barthélemy</option>
   <option value="SH">Saint Helena, Ascension and Tristan da Cunha</option>
   <option value="KN">Saint Kitts and Nevis</option>
   <option value="LC">Saint Lucia</option>
   <option value="MF">Saint Martin (French part)</option>
   <option value="PM">Saint Pierre and Miquelon</option>
   <option value="VC">Saint Vincent and the Grenadines</option>
   <option value="WS">Samoa</option>
   <option value="SM">San Marino</option>
   <option value="ST">Sao Tome and Principe</option>
   <option value="SA">Saudi Arabia</option>
   <option value="SN">Senegal</option>
   <option value="RS">Serbia</option>
   <option value="SC">Seychelles</option>
   <option value="SL">Sierra Leone</option>
   <option value="SG">Singapore</option>
   <option value="SK">Slovakia</option>
   <option value="SI">Slovenia</option>
   <option value="SB">Solomon Islands</option>
   <option value="SO">Somalia</option>
   <option value="ZA">South Africa</option>
   <option value="GS">South Georgia and the South Sandwich Islands</option>
   <option value="ES">Spain</option>
   <option value="LK">Sri Lanka</option>
   <option value="SD">Sudan</option>
   <option value="SR">Suriname</option>
   <option value="SJ">Svalbard and Jan Mayen</option>
   <option value="SZ">Swaziland</option>
   <option value="SE">Sweden</option>
   <option value="CH">Switzerland</option>
   <option value="SY">Syrian Arab Republic</option>
   <option value="TW">Taiwan, Province of China</option>
   <option value="TJ">Tajikistan</option>
   <option value="TZ">Tanzania, United Republic of</option>
   <option value="TH">Thailand</option>
   <option value="TL">Timor-Leste</option>
   <option value="TG">Togo</option>
   <option value="TK">Tokelau</option>
   <option value="TO">Tonga</option>
   <option value="TT">Trinidad and Tobago</option>
   <option value="TN">Tunisia</option>
   <option value="TR">Turkey</option>
   <option value="TM">Turkmenistan</option>
   <option value="TC">Turks and Caicos Islands</option>
   <option value="TV">Tuvalu</option>
   <option value="UG">Uganda</option>
   <option value="UA">Ukraine</option>
   <option value="AE">United Arab Emirates</option>
   <option value="GB">United Kingdom</option>
   <option value="US">United States</option>
   <option value="UM">United States Minor Outlying Islands</option>
   <option value="UY">Uruguay</option>
   <option value="UZ">Uzbekistan</option>
   <option value="VU">Vanuatu</option>
   <option value="VE">Venezuela, Bolivarian Republic of</option>
   <option value="VN">Viet Nam</option>
   <option value="VG">Virgin Islands, British</option>
   <option value="VI">Virgin Islands, U.S.</option>
   <option value="WF">Wallis and Futuna</option>
   <option value="EH">Western Sahara</option>
   <option value="YE">Yemen</option>
   <option value="ZM">Zambia</option>
   <option value="ZW">Zimbabwe</option>
</select>

Add CSS class under <head> tag.

.country_selector {
   cursor: text;
}
.country_selector {
   width: 400px;
   float: none;
   margin: auto;
   display: inline-block;
   text-align: left;
}

.country_selector.single .selectize-input:after {
   display: none !important;
}

.country_selector .selectize-input .item .flag-icon, .country_selector .selectize-dropdown .option .flag-icon{
   margin-right: 10px;
}

.country_selector.single .selectize-input, .country_selector.single .selectize-input input {
   cursor: text !important;
}

.country_selector .selectize-dropdown .option {
   cursor: pointer !important;
}

Add JS function under <script> tag in bottom or add in your JS file.

$('.country_selector').selectize({
    render: {
        option: function(data, escape) {
            return '<div class="option"><span class="flag-icon flag-icon-' + String(escape(data.value)).toLowerCase() + '"></span>' + escape(data.text) + '</div>';
        },
        item: function(data, escape) {
            return '<div class="item"><span class="flag-icon flag-icon-' + String(escape(data.value)).toLowerCase() + '"></span>' + escape(data.text) + '</div>';
        }
    },
});

Configuration :-

Refer to this documentation for more configuration.

Google Apps Script

What is Google Apps Script?

Google Apps Script (GAS) is a JavaScript based language to script/automate/customize Google Apps (Gsuite products). Google Apps for work has recently changed it’s name to GSuite. The list products is ever increasing, right now there are around 12 Gsuite products. Google Apps Script can be used to script most of these product.

Some interesting stuff you can do with GAS are

  1. Send automated email when Google form is submitted
  2. Finding email with bigger attachment in your gmail account.
  3. Writing add-ons to google docs and sheets

And many more. Google Apps Script offers full blown API to deal all the GSuite products. Unlike traditional languages GAS gets written and executed on google servers. You don’t have to download any thing or go through the pains of setting up development environment.  In this tutorial we will see how to write your first Google Apps Script program.

hello world using google apps script

Visit script.google.com . The interface looks like as shown below.

Start putting together the following program.

function createAndSendDocument() {

var doc = DocumentApp.create('Hello world');
doc.getBody().appendParagraph('Hello from GAS - This doc was created with google app script');

var email = Session.getActiveUser().getEmail();
var subject = doc.getName();
var url = doc.getUrl();
var body = 'Link to your doc : ' + url;

MailApp.sendEmail(lemail, subject, body);

}

What this program does is

  1. Create google document called ‘Hello World’.
  2. Add some text to newly created document.
  3. Get the email addressed of currently logged in user (you).
  4. Extract URL/Link for the created document.
  5. Mail it to the email address.

Now, you can save the script using Save option from File item. Your code file gets saved to your google drive. Later on you can always go back to google drive and open this script to make changes.

That’s it now, all you need to do is run this script either by clicking on Run button or selecting Run from menubar and click on function name displayed there. Pretty cool isn’t it ? You can do lot more interesting stuff using Google Apps Script. Visit the reference link included earlier in this post to find out about all the API calls supported by Google Apps Script.

 

How to blink browser tab

Have you ever wished to blink browser tab on certain activity to get user’s attention?

Here is a scenario: Suppose there is a chat application installed on your website. Now what if the user of your website has multiple tabs opened in his browser and there is an incoming message in your website? How will you make your user realize that there is an unread message? Of course you can play some music, but it has some limitations. For instance, user may be listening to some songs or speakers could be muted. If none of them is applicable then also he has to go through each and every single tab in his browser and find out the one which is playing that music.

Visual blinking is the best way to get user’s attention and the easiest way to achieve that is to keep blinking the title of your website until user returns.

Here’s a JavaScript function to do so:

var blinkTab = function(message) {
  var oldTitle = document.title,                                                           /* save original title */
      timeoutId,
      blink = function() { document.title = document.title == message ? ' ' : message; },  /* function to BLINK browser tab */
      clear = function() {                                                                 /* function to set title back to original */
        clearInterval(timeoutId);
        document.title = oldTitle;
        window.onmousemove = null;
        timeoutId = null;
      };

  if (!timeoutId) {
    timeoutId = setInterval(blink, 1000);
    window.onmousemove = clear;                                                            /* stop changing title on moving the mouse */
  }
};

Just execute the function like below and browser tab will start blinking:

blinkTab("your message");