Node.js Express Youtube Data API V3 Upload Video to Youtube in Javascript Full Project For Beginners

Node.js Express Youtube Data API V3 Upload Video to Youtube in Javascript Full Project For Beginners

Welcome folks today i am back with another blog post in this post we will be uploading youtube videos in node.js using the youtube data api v3. In this tutorial we will be using the express framework to build the server.All the source code is given below. A step by step youtube video is also shown below.

 

Screenshots

 

 

Requirements

 

Express : Server on which the app will be running

googleapis : It will be the official google client library for authentication for node.js. We will be using this library for authentication

fs: we will be using this file system module which is built in module for nodejs to store files

multer: This will be the library for uploading files on the express server

ejs: It will be the template engine which will be used in the node.js application

nodemon: It will be the library to automatically restart the application when any changes takes place

 

const fs = require("fs");
const express = require("express");
const multer = require("multer");
const OAuth2Data = require("./credentials.json");
var title, description;
var tags = [];

const { google } = require("googleapis");

const app = express();

const CLIENT_ID = OAuth2Data.web.client_id;
const CLIENT_SECRET = OAuth2Data.web.client_secret;
const REDIRECT_URL = OAuth2Data.web.redirect_uris[0];

const oAuth2Client = new google.auth.OAuth2(
  CLIENT_ID,
  CLIENT_SECRET,
  REDIRECT_URL
);
var authed = false;

// If modifying these scopes, delete token.json.
const SCOPES =
  "https://www.googleapis.com/auth/youtube.upload https://www.googleapis.com/auth/userinfo.profile";

app.set("view engine", "ejs");

var Storage = multer.diskStorage({
  destination: function (req, file, callback) {
    callback(null, "./videos");
  },
  filename: function (req, file, callback) {
    callback(null, file.fieldname + "_" + Date.now() + "_" + file.originalname);
  },
});

var upload = multer({
  storage: Storage,
}).single("file"); //Field name and max count

app.get("/", (req, res) => {
  if (!authed) {
    // Generate an OAuth URL and redirect there
    var url = oAuth2Client.generateAuthUrl({
      access_type: "offline",
      scope: SCOPES,
    });
    console.log(url);
    res.render("index", { url: url });
  } else {
    var oauth2 = google.oauth2({
      auth: oAuth2Client,
      version: "v2",
    });
    oauth2.userinfo.get(function (err, response) {
      if (err) {
        console.log(err);
      } else {
        console.log(response.data);
        name = response.data.name;
        pic = response.data.picture;
        res.render("success", {
          name: response.data.name,
          pic: response.data.picture,
          success: false,
        });
      }
    });
  }
});

app.post("/upload", (req, res) => {
  upload(req, res, function (err) {
    if (err) {
      console.log(err);
      return res.end("Something went wrong");
    } else {
      console.log(req.file.path);
      title = req.body.title;
      description = req.body.description;
      tags = req.body.tags;
      console.log(title);
      console.log(description);
      console.log(tags);
      const youtube = google.youtube({ version: "v3", auth: oAuth2Client });
      console.log(youtube)
      youtube.videos.insert(
        {
          resource: {
            // Video title and description
            snippet: {
                title:title,
                description:description
            },
            // I don't want to spam my subscribers
            status: {
              privacyStatus: "private",
            },
          },
          // This is for the callback function
          part: "snippet,status",

          // Create the readable stream to upload the video
          media: {
            body: fs.createReadStream(req.file.path)
          },
        },
        (err, data) => {
          if(err) throw err
          console.log(data)
          console.log("Done.");
          fs.unlinkSync(req.file.path);
          res.render("success", { name: name, pic: pic, success: true });
        }
      );
    }
  });
});

app.get("/logout", (req, res) => {
  authed = false;
  res.redirect("/");
});

app.get("/google/callback", function (req, res) {
  const code = req.query.code;
  if (code) {
    // Get an access token based on our OAuth code
    oAuth2Client.getToken(code, function (err, tokens) {
      if (err) {
        console.log("Error authenticating");
        console.log(err);
      } else {
        console.log("Successfully authenticated");
        console.log(tokens);
        oAuth2Client.setCredentials(tokens);

        authed = true;
        res.redirect("/");
      }
    });
  }
});

app.listen(5000, () => {
  console.log("App is listening on Port 5000");
});

 

<!doctype html>
<html>
<head>
    <title>Node Authentication</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
    <style>
        body        { padding-top:80px; }
    </style>
</head>
<body>
<div class="container">

    <div class="jumbotron text-center">
        <h1><span class="fa fa-lock"></span> Youtube Video Upload</h1>

        <p>Login or Register with:</p>

        <a href="<%=url%>" class="btn btn-danger"><span class="fa fa-youtube"></span> Upload Video</a>

    </div>

</div>
</body>
</html>

 

<!DOCTYPE html>
<html>
  <head>
    <title>Node Authentication</title>
    <link
      rel="stylesheet"
      href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"
    />
    <link
      rel="stylesheet"
      href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"
    />
    <style>
      body {
        padding-top: 80px;
        word-wrap: break-word;
      }
      .bootstrap-tagsinput {
    background-color: #fff;
    border: 1px solid #ccc;
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
    display: inline-block;
    padding: 4px 6px;
    color: #555;
    vertical-align: middle;
    border-radius: 4px;
    max-width: 100%;
    line-height: 22px;
    cursor: text;
  }
  .bootstrap-tagsinput input {
    border: none;
    box-shadow: none;
    outline: none;
    background-color: transparent;
    padding: 0 6px;
    margin: 0;
    width: auto;
    max-width: inherit;
  }
  .bootstrap-tagsinput.form-control input::-moz-placeholder {
    color: #777;
    opacity: 1;
  }
  .bootstrap-tagsinput.form-control input:-ms-input-placeholder {
    color: #777;
  }
  .bootstrap-tagsinput.form-control input::-webkit-input-placeholder {
    color: #777;
  }
  .bootstrap-tagsinput input:focus {
    border: none;
    box-shadow: none;
  }
  .bootstrap-tagsinput .tag {
    margin-right: 2px;
    color: white;
  }
  .bootstrap-tagsinput .tag [data-role="remove"] {
    margin-left: 8px;
    cursor: pointer;
  }
  .bootstrap-tagsinput .tag [data-role="remove"]:after {
    content: "x";
    padding: 0px 2px;
  }
  .bootstrap-tagsinput .tag [data-role="remove"]:hover {
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
  }
  .bootstrap-tagsinput .tag [data-role="remove"]:hover:active {
    box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
  }
  
    </style>

  </head>
  <body>
    <div class="container">
      <div class="page-header text-center">
        <h1><span class="fa fa-anchor"></span> Profile Page</h1>
        <a href="/logout" class="btn btn-default btn-sm">Logout</a>
      </div>

      <div class="row">
        <!-- GOOGLE INFORMATION -->
        <div class="col-sm-6">
          <div class="well">
            <h3 class="text-danger">
              <span class="fa fa-youtube"></span> Youtube Channel
            </h3>

            <p>
              <strong>name</strong>: <%= name %>
              <br />
              <strong>pic:</strong>:
              <img src="<%=pic%>" width="200" height="200" alt="" />
            </p>
          </div>
        </div>

        <div class="col-sm-6">
          <div class="well">
            <h3 class="text-danger">
              <span class="fa fa-youtube"></span> Upload Video to Youtube
            </h3>

            <% if (success) { %>
            <div class="alert alert-success alert-dismissible">
              <a href="#" class="close" data-dismiss="alert" aria-label="close"
                >×</a
              >
              <strong>Success!</strong> Your Video is Uploaded to Youtube.
            </div>
            <%}%>
            <form action="/upload" method="POST" enctype="multipart/form-data">
              <div class="form-group">
                <div class="form-group">
                    <input type="text" name="title" placeholder="Title" required class="form-control">
                </div>
                <div class="form-group">
                    <textarea name="description" class="form-control" cols="30" rows="10" placeholder="description"></textarea>
                </div>
                <div class="form-group">
                    <input id="tags-input" type="text" class="form-control" name="tags" data-role="tagsinput" placeholder="tags"/>
                </div>
                <div class="form-group">
                <input
                  type="file"
                  class="form-control"
                  name="file"
                  required
                  id=""
                />
                </div>
              </div>
              <div class="form-group">
                <button class="btn btn-block btn-danger">
                  Upload Video
                </button>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
  </body>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
  <script>
      (function ($) {
    "use strict";
  
    var defaultOptions = {
      tagClass: function(item) {
        return 'label label-info';
      },
      itemValue: function(item) {
        return item ? item.toString() : item;
      },
      itemText: function(item) {
        return this.itemValue(item);
      },
      itemTitle: function(item) {
        return null;
      },
      freeInput: true,
      addOnBlur: true,
      maxTags: undefined,
      maxChars: undefined,
      confirmKeys: [13, 44],
      delimiter: ',',
      delimiterRegex: null,
      cancelConfirmKeysOnEmpty: true,
      onTagExists: function(item, $tag) {
        $tag.hide().fadeIn();
      },
      trimValue: false,
      allowDuplicates: false
    };
  
    /**
     * Constructor function
     */
    function TagsInput(element, options) {
      this.itemsArray = [];
  
      this.$element = $(element);
      this.$element.hide();
  
      this.isSelect = (element.tagName === 'SELECT');
      this.multiple = (this.isSelect && element.hasAttribute('multiple'));
      this.objectItems = options && options.itemValue;
      this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : '';
      this.inputSize = Math.max(1, this.placeholderText.length);
  
      this.$container = $('<div class="bootstrap-tagsinput"></div>');
      this.$input = $('<input type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
  
      this.$element.before(this.$container);
  
      this.build(options);
    }
  
    TagsInput.prototype = {
      constructor: TagsInput,
  
      /**
       * Adds the given item as a new tag. Pass true to dontPushVal to prevent
       * updating the elements val()
       */
      add: function(item, dontPushVal, options) {
        var self = this;
  
        if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags)
          return;
  
        // Ignore falsey values, except false
        if (item !== false && !item)
          return;
  
        // Trim value
        if (typeof item === "string" && self.options.trimValue) {
          item = $.trim(item);
        }
  
        // Throw an error when trying to add an object while the itemValue option was not set
        if (typeof item === "object" && !self.objectItems)
          throw("Can't add objects when itemValue option is not set");
  
        // Ignore strings only containg whitespace
        if (item.toString().match(/^\s*$/))
          return;
  
        // If SELECT but not multiple, remove current tag
        if (self.isSelect && !self.multiple && self.itemsArray.length > 0)
          self.remove(self.itemsArray[0]);
  
        if (typeof item === "string" && this.$element[0].tagName === 'INPUT') {
          var delimiter = (self.options.delimiterRegex) ? self.options.delimiterRegex : self.options.delimiter;
          var items = item.split(delimiter);
          if (items.length > 1) {
            for (var i = 0; i < items.length; i++) {
              this.add(items[i], true);
            }
  
            if (!dontPushVal)
              self.pushVal();
            return;
          }
        }
  
        var itemValue = self.options.itemValue(item),
            itemText = self.options.itemText(item),
            tagClass = self.options.tagClass(item),
            itemTitle = self.options.itemTitle(item);
  
        // Ignore items allready added
        var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0];
        if (existing && !self.options.allowDuplicates) {
          // Invoke onTagExists
          if (self.options.onTagExists) {
            var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; });
            self.options.onTagExists(item, $existingTag);
          }
          return;
        }
  
        // if length greater than limit
        if (self.items().toString().length + item.length + 1 > self.options.maxInputLength)
          return;
  
        // raise beforeItemAdd arg
        var beforeItemAddEvent = $.Event('beforeItemAdd', { item: item, cancel: false, options: options});
        self.$element.trigger(beforeItemAddEvent);
        if (beforeItemAddEvent.cancel)
          return;
  
        // register item in internal array and map
        self.itemsArray.push(item);
  
        // add a tag element
  
        var $tag = $('<span class="tag ' + htmlEncode(tagClass) + (itemTitle !== null ? ('" title="' + itemTitle) : '') + '">' + htmlEncode(itemText) + '<span data-role="remove"></span></span>');
        $tag.data('item', item);
        self.findInputWrapper().before($tag);
        $tag.after(' ');
  
        // add <option /> if item represents a value not present in one of the <select />'s options
        if (self.isSelect && !$('option[value="' + encodeURIComponent(itemValue) + '"]',self.$element)[0]) {
          var $option = $('<option selected>' + htmlEncode(itemText) + '</option>');
          $option.data('item', item);
          $option.attr('value', itemValue);
          self.$element.append($option);
        }
  
        if (!dontPushVal)
          self.pushVal();
  
        // Add class when reached maxTags
        if (self.options.maxTags === self.itemsArray.length || self.items().toString().length === self.options.maxInputLength)
          self.$container.addClass('bootstrap-tagsinput-max');
  
        self.$element.trigger($.Event('itemAdded', { item: item, options: options }));
      },
  
      /**
       * Removes the given item. Pass true to dontPushVal to prevent updating the
       * elements val()
       */
      remove: function(item, dontPushVal, options) {
        var self = this;
  
        if (self.objectItems) {
          if (typeof item === "object")
            item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) ==  self.options.itemValue(item); } );
          else
            item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) ==  item; } );
  
          item = item[item.length-1];
        }
  
        if (item) {
          var beforeItemRemoveEvent = $.Event('beforeItemRemove', { item: item, cancel: false, options: options });
          self.$element.trigger(beforeItemRemoveEvent);
          if (beforeItemRemoveEvent.cancel)
            return;
  
          $('.tag', self.$container).filter(function() { return $(this).data('item') === item; }).remove();
          $('option', self.$element).filter(function() { return $(this).data('item') === item; }).remove();
          if($.inArray(item, self.itemsArray) !== -1)
            self.itemsArray.splice($.inArray(item, self.itemsArray), 1);
        }
  
        if (!dontPushVal)
          self.pushVal();
  
        // Remove class when reached maxTags
        if (self.options.maxTags > self.itemsArray.length)
          self.$container.removeClass('bootstrap-tagsinput-max');
  
        self.$element.trigger($.Event('itemRemoved',  { item: item, options: options }));
      },
  
      /**
       * Removes all items
       */
      removeAll: function() {
        var self = this;
  
        $('.tag', self.$container).remove();
        $('option', self.$element).remove();
  
        while(self.itemsArray.length > 0)
          self.itemsArray.pop();
  
        self.pushVal();
      },
  
      /**
       * Refreshes the tags so they match the text/value of their corresponding
       * item.
       */
      refresh: function() {
        var self = this;
        $('.tag', self.$container).each(function() {
          var $tag = $(this),
              item = $tag.data('item'),
              itemValue = self.options.itemValue(item),
              itemText = self.options.itemText(item),
              tagClass = self.options.tagClass(item);
  
            // Update tag's class and inner text
            $tag.attr('class', null);
            $tag.addClass('tag ' + htmlEncode(tagClass));
            $tag.contents().filter(function() {
              return this.nodeType == 3;
            })[0].nodeValue = htmlEncode(itemText);
  
            if (self.isSelect) {
              var option = $('option', self.$element).filter(function() { return $(this).data('item') === item; });
              option.attr('value', itemValue);
            }
        });
      },
  
      /**
       * Returns the items added as tags
       */
      items: function() {
        return this.itemsArray;
      },
  
      /**
       * Assembly value by retrieving the value of each item, and set it on the
       * element.
       */
      pushVal: function() {
        var self = this,
            val = $.map(self.items(), function(item) {
              return self.options.itemValue(item).toString();
            });
  
        self.$element.val(val, true).trigger('change');
      },
  
      /**
       * Initializes the tags input behaviour on the element
       */
      build: function(options) {
        var self = this;
  
        self.options = $.extend({}, defaultOptions, options);
        // When itemValue is set, freeInput should always be false
        if (self.objectItems)
          self.options.freeInput = false;
  
        makeOptionItemFunction(self.options, 'itemValue');
        makeOptionItemFunction(self.options, 'itemText');
        makeOptionFunction(self.options, 'tagClass');
  
        // Typeahead Bootstrap version 2.3.2
        if (self.options.typeahead) {
          var typeahead = self.options.typeahead || {};
  
          makeOptionFunction(typeahead, 'source');
  
          self.$input.typeahead($.extend({}, typeahead, {
            source: function (query, process) {
              function processItems(items) {
                var texts = [];
  
                for (var i = 0; i < items.length; i++) {
                  var text = self.options.itemText(items[i]);
                  map[text] = items[i];
                  texts.push(text);
                }
                process(texts);
              }
  
              this.map = {};
              var map = this.map,
                  data = typeahead.source(query);
  
              if ($.isFunction(data.success)) {
                // support for Angular callbacks
                data.success(processItems);
              } else if ($.isFunction(data.then)) {
                // support for Angular promises
                data.then(processItems);
              } else {
                // support for functions and jquery promises
                $.when(data)
                 .then(processItems);
              }
            },
            updater: function (text) {
              self.add(this.map[text]);
              return this.map[text];
            },
            matcher: function (text) {
              return (text.toLowerCase().indexOf(this.query.trim().toLowerCase()) !== -1);
            },
            sorter: function (texts) {
              return texts.sort();
            },
            highlighter: function (text) {
              var regex = new RegExp( '(' + this.query + ')', 'gi' );
              return text.replace( regex, "<strong>$1</strong>" );
            }
          }));
        }
  
        // typeahead.js
        if (self.options.typeaheadjs) {
            var typeaheadConfig = null;
            var typeaheadDatasets = {};
  
            // Determine if main configurations were passed or simply a dataset
            var typeaheadjs = self.options.typeaheadjs;
            if ($.isArray(typeaheadjs)) {
              typeaheadConfig = typeaheadjs[0];
              typeaheadDatasets = typeaheadjs[1];
            } else {
              typeaheadDatasets = typeaheadjs;
            }
  
            self.$input.typeahead(typeaheadConfig, typeaheadDatasets).on('typeahead:selected', $.proxy(function (obj, datum) {
              if (typeaheadDatasets.valueKey)
                self.add(datum[typeaheadDatasets.valueKey]);
              else
                self.add(datum);
              self.$input.typeahead('val', '');
            }, self));
        }
  
        self.$container.on('click', $.proxy(function(event) {
          if (! self.$element.attr('disabled')) {
            self.$input.removeAttr('disabled');
          }
          self.$input.focus();
        }, self));
  
          if (self.options.addOnBlur && self.options.freeInput) {
            self.$input.on('focusout', $.proxy(function(event) {
                // HACK: only process on focusout when no typeahead opened, to
                //       avoid adding the typeahead text as tag
                if ($('.typeahead, .twitter-typeahead', self.$container).length === 0) {
                  self.add(self.$input.val());
                  self.$input.val('');
                }
            }, self));
          }
  
  
        self.$container.on('keydown', 'input', $.proxy(function(event) {
          var $input = $(event.target),
              $inputWrapper = self.findInputWrapper();
  
          if (self.$element.attr('disabled')) {
            self.$input.attr('disabled', 'disabled');
            return;
          }
  
          switch (event.which) {
            // BACKSPACE
            case 8:
              if (doGetCaretPosition($input[0]) === 0) {
                var prev = $inputWrapper.prev();
                if (prev.length) {
                  self.remove(prev.data('item'));
                }
              }
              break;
  
            // DELETE
            case 46:
              if (doGetCaretPosition($input[0]) === 0) {
                var next = $inputWrapper.next();
                if (next.length) {
                  self.remove(next.data('item'));
                }
              }
              break;
  
            // LEFT ARROW
            case 37:
              // Try to move the input before the previous tag
              var $prevTag = $inputWrapper.prev();
              if ($input.val().length === 0 && $prevTag[0]) {
                $prevTag.before($inputWrapper);
                $input.focus();
              }
              break;
            // RIGHT ARROW
            case 39:
              // Try to move the input after the next tag
              var $nextTag = $inputWrapper.next();
              if ($input.val().length === 0 && $nextTag[0]) {
                $nextTag.after($inputWrapper);
                $input.focus();
              }
              break;
           default:
               // ignore
           }
  
          // Reset internal input's size
          var textLength = $input.val().length,
              wordSpace = Math.ceil(textLength / 5),
              size = textLength + wordSpace + 1;
          $input.attr('size', Math.max(this.inputSize, $input.val().length));
        }, self));
  
        self.$container.on('keypress', 'input', $.proxy(function(event) {
           var $input = $(event.target);
  
           if (self.$element.attr('disabled')) {
              self.$input.attr('disabled', 'disabled');
              return;
           }
  
           var text = $input.val(),
           maxLengthReached = self.options.maxChars && text.length >= self.options.maxChars;
           if (self.options.freeInput && (keyCombinationInList(event, self.options.confirmKeys) || maxLengthReached)) {
              // Only attempt to add a tag if there is data in the field
              if (text.length !== 0) {
                 self.add(maxLengthReached ? text.substr(0, self.options.maxChars) : text);
                 $input.val('');
              }
  
              // If the field is empty, let the event triggered fire as usual
              if (self.options.cancelConfirmKeysOnEmpty === false) {
                 event.preventDefault();
              }
           }
  
           // Reset internal input's size
           var textLength = $input.val().length,
              wordSpace = Math.ceil(textLength / 5),
              size = textLength + wordSpace + 1;
           $input.attr('size', Math.max(this.inputSize, $input.val().length));
        }, self));
  
        // Remove icon clicked
        self.$container.on('click', '[data-role=remove]', $.proxy(function(event) {
          if (self.$element.attr('disabled')) {
            return;
          }
          self.remove($(event.target).closest('.tag').data('item'));
        }, self));
  
        // Only add existing value as tags when using strings as tags
        if (self.options.itemValue === defaultOptions.itemValue) {
          if (self.$element[0].tagName === 'INPUT') {
              self.add(self.$element.val());
          } else {
            $('option', self.$element).each(function() {
              self.add($(this).attr('value'), true);
            });
          }
        }
      },
  
      /**
       * Removes all tagsinput behaviour and unregsiter all event handlers
       */
      destroy: function() {
        var self = this;
  
        // Unbind events
        self.$container.off('keypress', 'input');
        self.$container.off('click', '[role=remove]');
  
        self.$container.remove();
        self.$element.removeData('tagsinput');
        self.$element.show();
      },
  
      /**
       * Sets focus on the tagsinput
       */
      focus: function() {
        this.$input.focus();
      },
  
      /**
       * Returns the internal input element
       */
      input: function() {
        return this.$input;
      },
  
      /**
       * Returns the element which is wrapped around the internal input. This
       * is normally the $container, but typeahead.js moves the $input element.
       */
      findInputWrapper: function() {
        var elt = this.$input[0],
            container = this.$container[0];
        while(elt && elt.parentNode !== container)
          elt = elt.parentNode;
  
        return $(elt);
      }
    };
  
    /**
     * Register JQuery plugin
     */
    $.fn.tagsinput = function(arg1, arg2, arg3) {
      var results = [];
  
      this.each(function() {
        var tagsinput = $(this).data('tagsinput');
        // Initialize a new tags input
        if (!tagsinput) {
            tagsinput = new TagsInput(this, arg1);
            $(this).data('tagsinput', tagsinput);
            results.push(tagsinput);
  
            if (this.tagName === 'SELECT') {
                $('option', $(this)).attr('selected', 'selected');
            }
  
            // Init tags from $(this).val()
            $(this).val($(this).val());
        } else if (!arg1 && !arg2) {
            // tagsinput already exists
            // no function, trying to init
            results.push(tagsinput);
        } else if(tagsinput[arg1] !== undefined) {
            // Invoke function on existing tags input
              if(tagsinput[arg1].length === 3 && arg3 !== undefined){
                 var retVal = tagsinput[arg1](arg2, null, arg3);
              }else{
                 var retVal = tagsinput[arg1](arg2);
              }
            if (retVal !== undefined)
                results.push(retVal);
        }
      });
  
      if ( typeof arg1 == 'string') {
        // Return the results from the invoked function calls
        return results.length > 1 ? results : results[0];
      } else {
        return results;
      }
    };
  
    $.fn.tagsinput.Constructor = TagsInput;
  
    /**
     * Most options support both a string or number as well as a function as
     * option value. This function makes sure that the option with the given
     * key in the given options is wrapped in a function
     */
    function makeOptionItemFunction(options, key) {
      if (typeof options[key] !== 'function') {
        var propertyName = options[key];
        options[key] = function(item) { return item[propertyName]; };
      }
    }
    function makeOptionFunction(options, key) {
      if (typeof options[key] !== 'function') {
        var value = options[key];
        options[key] = function() { return value; };
      }
    }
    /**
     * HtmlEncodes the given value
     */
    var htmlEncodeContainer = $('<div />');
    function htmlEncode(value) {
      if (value) {
        return htmlEncodeContainer.text(value).html();
      } else {
        return '';
      }
    }
  
    /**
     * Returns the position of the caret in the given input field
     * http://flightschool.acylt.com/devnotes/caret-position-woes/
     */
    function doGetCaretPosition(oField) {
      var iCaretPos = 0;
      if (document.selection) {
        oField.focus ();
        var oSel = document.selection.createRange();
        oSel.moveStart ('character', -oField.value.length);
        iCaretPos = oSel.text.length;
      } else if (oField.selectionStart || oField.selectionStart == '0') {
        iCaretPos = oField.selectionStart;
      }
      return (iCaretPos);
    }
  
    /**
      * Returns boolean indicates whether user has pressed an expected key combination.
      * @param object keyPressEvent: JavaScript event object, refer
      *     http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
      * @param object lookupList: expected key combinations, as in:
      *     [13, {which: 188, shiftKey: true}]
      */
    function keyCombinationInList(keyPressEvent, lookupList) {
        var found = false;
        $.each(lookupList, function (index, keyCombination) {
            if (typeof (keyCombination) === 'number' && keyPressEvent.which === keyCombination) {
                found = true;
                return false;
            }
  
            if (keyPressEvent.which === keyCombination.which) {
                var alt = !keyCombination.hasOwnProperty('altKey') || keyPressEvent.altKey === keyCombination.altKey,
                    shift = !keyCombination.hasOwnProperty('shiftKey') || keyPressEvent.shiftKey === keyCombination.shiftKey,
                    ctrl = !keyCombination.hasOwnProperty('ctrlKey') || keyPressEvent.ctrlKey === keyCombination.ctrlKey;
                if (alt && shift && ctrl) {
                    found = true;
                    return false;
                }
            }
        });
  
        return found;
    }
  
    /**
     * Initialize tagsinput behaviour on inputs and selects which have
     * data-role=tagsinput
     */
    $(function() {
      $("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput();
    });
  })(window.jQuery);
  

  $(window).keydown(function(event){
    if(event.keyCode == 13) {
      event.preventDefault();
      return false;
    }
  });
  </script>
</html>

 

See also  Join Javascript Whatsapp Group Link For Developers in 2021 | Javascript Whatsapp Group Links For Javascript Developers | Whatsapp Group Links For Javascript Programmers

DOWNLOAD SOURCE CODE

 

Leave a Reply