Streaming live at 10am (PST)

Custom Code Integration

Hello Everyone,

I am building an interactive website to engage with my customers. I am trying to add this interactive questionnaire from the following demo site, however with specific questions that I would like to ask my audience… https://tympanus.net/codrops/2014/07/30/fullscreen-form-interface/

Is anyone able to help me better understand how the embedded function on WebFlow works?

I have the the source code downloaded, however it does not seem to embed properly. Please let me know! Thank you!

1 Like

How does it not embed properly? Can you please provide more information Posting Guidelines for the Code Help Category including sharing your site’s published URL?

Hi Samliew,

The code line that I downloaded is provided below. When I copy and paste that code into the DIV and custom < > section, the error message shows this (See screenshot):

19%20PM|684x500

CODE:

/**

  • fullscreenForm.js v1.0.0

  • http://www.codrops.com

  • Licensed under the MIT license.

  • http://www.opensource.org/licenses/mit-license.php

  • Copyright 2014, Codrops

  • http://www.codrops.com
    */
    ;( function( window ) {

    ‘use strict’;

    var support = { animations : Modernizr.cssanimations },
    animEndEventNames = { ‘WebkitAnimation’ : ‘webkitAnimationEnd’, ‘OAnimation’ : ‘oAnimationEnd’, ‘msAnimation’ : ‘MSAnimationEnd’, ‘animation’ : ‘animationend’ },
    // animation end event name
    animEndEventName = animEndEventNames[ Modernizr.prefixed( ‘animation’ ) ];

    /**

    • extend obj function
      */
      function extend( a, b ) {
      for( var key in b ) {
      if( b.hasOwnProperty( key ) ) {
      a[key] = b[key];
      }
      }
      return a;
      }

    /**

    • createElement function
    • creates an element with tag = tag, className = opt.cName, innerHTML = opt.inner and appends it to opt.appendTo
      */
      function createElement( tag, opt ) {
      var el = document.createElement( tag )
      if( opt ) {
      if( opt.cName ) {
      el.className = opt.cName;
      }
      if( opt.inner ) {
      el.innerHTML = opt.inner;
      }
      if( opt.appendTo ) {
      opt.appendTo.appendChild( el );
      }
      }
      return el;
      }

    /**

    • FForm function
      */
      function FForm( el, options ) {
      this.el = el;
      this.options = extend( {}, this.options );
      extend( this.options, options );
      this._init();
      }

    /**

    • FForm options
      */
      FForm.prototype.options = {
      // show progress bar
      ctrlProgress : true,
      // show navigation dots
      ctrlNavDots : true,
      // show [current field]/[total fields] status
      ctrlNavPosition : true,
      // reached the review and submit step
      onReview : function() { return false; }
      };

    /**

    • init function

    • initialize and cache some vars
      */
      FForm.prototype._init = function() {
      // the form element
      this.formEl = this.el.querySelector( ‘form’ );

      // list of fields
      this.fieldsList = this.formEl.querySelector( ‘ol.fs-fields’ );

      // current field position
      this.current = 0;

      // all fields
      this.fields = [].slice.call( this.fieldsList.children );

      // total fields
      this.fieldsCount = this.fields.length;

      // show first field
      classie.add( this.fields[ this.current ], ‘fs-current’ );

      // create/add controls
      this._addControls();

      // create/add messages
      this._addErrorMsg();

      // init events
      this._initEvents();
      };

    /**

    • addControls function

    • create and insert the structure for the controls
      */
      FForm.prototype._addControls = function() {
      // main controls wrapper
      this.ctrls = createElement( ‘div’, { cName : ‘fs-controls’, appendTo : this.el } );

      // continue button (jump to next field)
      this.ctrlContinue = createElement( ‘button’, { cName : ‘fs-continue’, inner : ‘Continue’, appendTo : this.ctrls } );
      this._showCtrl( this.ctrlContinue );

      // navigation dots
      if( this.options.ctrlNavDots ) {
      this.ctrlNav = createElement( ‘nav’, { cName : ‘fs-nav-dots’, appendTo : this.ctrls } );
      var dots = ‘’;
      for( var i = 0; i < this.fieldsCount; ++i ) {
      dots += i === this.current ? ‘’ : ‘’;
      }
      this.ctrlNav.innerHTML = dots;
      this._showCtrl( this.ctrlNav );
      this.ctrlNavDots = [].slice.call( this.ctrlNav.children );
      }

      // field number status
      if( this.options.ctrlNavPosition ) {
      this.ctrlFldStatus = createElement( ‘span’, { cName : ‘fs-numbers’, appendTo : this.ctrls } );

       // current field placeholder
       this.ctrlFldStatusCurr = createElement( 'span', { cName : 'fs-number-current', inner : Number( this.current + 1 ) } );
       this.ctrlFldStatus.appendChild( this.ctrlFldStatusCurr );
      
       // total fields placeholder
       this.ctrlFldStatusTotal = createElement( 'span', { cName : 'fs-number-total', inner : this.fieldsCount } );
       this.ctrlFldStatus.appendChild( this.ctrlFldStatusTotal );
       this._showCtrl( this.ctrlFldStatus );
      

      }

      // progress bar
      if( this.options.ctrlProgress ) {
      this.ctrlProgress = createElement( ‘div’, { cName : ‘fs-progress’, appendTo : this.ctrls } );
      this._showCtrl( this.ctrlProgress );
      }
      }

    /**

    • addErrorMsg function
    • create and insert the structure for the error message
      */
      FForm.prototype._addErrorMsg = function() {
      // error message
      this.msgError = createElement( ‘span’, { cName : ‘fs-message-error’, appendTo : this.el } );
      }

    /**

    • init events
      */
      FForm.prototype._initEvents = function() {
      var self = this;

      // show next field
      this.ctrlContinue.addEventListener( ‘click’, function() {
      self._nextField();
      } );

      // navigation dots
      if( this.options.ctrlNavDots ) {
      this.ctrlNavDots.forEach( function( dot, pos ) {
      dot.addEventListener( ‘click’, function() {
      self._showField( pos );
      } );
      } );
      }

      // jump to next field without clicking the continue button (for fields/list items with the attribute “data-input-trigger”)
      this.fields.forEach( function( fld ) {
      if( fld.hasAttribute( ‘data-input-trigger’ ) ) {
      var input = fld.querySelector( ‘input[type=“radio”]’ ) || /fld.querySelector( ‘.cs-select’ ) ||/ fld.querySelector( ‘select’ ); // assuming only radio and select elements (TODO: exclude multiple selects)
      if( !input ) return;

       	switch( input.tagName.toLowerCase() ) {
       		case 'select' : 
       			input.addEventListener( 'change', function() { self._nextField(); } );
       			break;
      
       		case 'input' : 
       			[].slice.call( fld.querySelectorAll( 'input[type="radio"]' ) ).forEach( function( inp ) {
       				inp.addEventListener( 'change', function(ev) { self._nextField(); } );
       			} ); 
       			break;
      
       		/*
       		// for our custom select we would do something like:
       		case 'div' : 
       			[].slice.call( fld.querySelectorAll( 'ul > li' ) ).forEach( function( inp ) {
       				inp.addEventListener( 'click', function(ev) { self._nextField(); } );
       			} ); 
       			break;
       		*/
       	}
       }
      

      } );

      // keyboard navigation events - jump to next field when pressing enter
      document.addEventListener( ‘keydown’, function( ev ) {
      if( !self.isLastStep && ev.target.tagName.toLowerCase() !== ‘textarea’ ) {
      var keyCode = ev.keyCode || ev.which;
      if( keyCode === 13 ) {
      ev.preventDefault();
      self._nextField();
      }
      }
      } );
      };

    /**

    • nextField function

    • jumps to the next field
      */
      FForm.prototype._nextField = function( backto ) {
      if( this.isLastStep || !this._validade() || this.isAnimating ) {
      return false;
      }
      this.isAnimating = true;

      // check if on last step
      this.isLastStep = this.current === this.fieldsCount - 1 && backto === undefined ? true : false;

      // clear any previous error messages
      this._clearError();

      // current field
      var currentFld = this.fields[ this.current ];

      // save the navigation direction
      this.navdir = backto !== undefined ? backto < this.current ? ‘prev’ : ‘next’ : ‘next’;

      // update current field
      this.current = backto !== undefined ? backto : this.current + 1;

      if( backto === undefined ) {
      // update progress bar (unless we navigate backwards)
      this._progress();

       // save farthest position so far
       this.farthest = this.current;
      

      }

      // add class “fs-display-next” or “fs-display-prev” to the list of fields
      classie.add( this.fieldsList, ‘fs-display-’ + this.navdir );

      // remove class “fs-current” from current field and add it to the next one
      // also add class “fs-show” to the next field and the class “fs-hide” to the current one
      classie.remove( currentFld, ‘fs-current’ );
      classie.add( currentFld, ‘fs-hide’ );

      if( !this.isLastStep ) {
      // update nav
      this._updateNav();

       // change the current field number/status
       this._updateFieldNumber();
      
       var nextField = this.fields[ this.current ];
       classie.add( nextField, 'fs-current' );
       classie.add( nextField, 'fs-show' );
      

      }

      // after animation ends remove added classes from fields
      var self = this,
      onEndAnimationFn = function( ev ) {
      if( support.animations ) {
      this.removeEventListener( animEndEventName, onEndAnimationFn );
      }

       	classie.remove( self.fieldsList, 'fs-display-' + self.navdir );
       	classie.remove( currentFld, 'fs-hide' );
      
       	if( self.isLastStep ) {
       		// show the complete form and hide the controls
       		self._hideCtrl( self.ctrlNav );
       		self._hideCtrl( self.ctrlProgress );
       		self._hideCtrl( self.ctrlContinue );
       		self._hideCtrl( self.ctrlFldStatus );
       		// replace class fs-form-full with fs-form-overview
       		classie.remove( self.formEl, 'fs-form-full' );
       		classie.add( self.formEl, 'fs-form-overview' );
       		classie.add( self.formEl, 'fs-show' );
       		// callback
       		self.options.onReview();
       	}
       	else {
       		classie.remove( nextField, 'fs-show' );
       		
       		if( self.options.ctrlNavPosition ) {
       			self.ctrlFldStatusCurr.innerHTML = self.ctrlFldStatusNew.innerHTML;
       			self.ctrlFldStatus.removeChild( self.ctrlFldStatusNew );
       			classie.remove( self.ctrlFldStatus, 'fs-show-' + self.navdir );
       		}
       	}
       	self.isAnimating = false;
       };
      

      if( support.animations ) {
      if( this.navdir === ‘next’ ) {
      if( this.isLastStep ) {
      currentFld.querySelector( ‘.fs-anim-upper’ ).addEventListener( animEndEventName, onEndAnimationFn );
      }
      else {
      nextField.querySelector( ‘.fs-anim-lower’ ).addEventListener( animEndEventName, onEndAnimationFn );
      }
      }
      else {
      nextField.querySelector( ‘.fs-anim-upper’ ).addEventListener( animEndEventName, onEndAnimationFn );
      }
      }
      else {
      onEndAnimationFn();
      }
      }

    /**

    • showField function
    • jumps to the field at position pos
      */
      FForm.prototype._showField = function( pos ) {
      if( pos === this.current || pos < 0 || pos > this.fieldsCount - 1 ) {
      return false;
      }
      this._nextField( pos );
      }

    /**

    • updateFieldNumber function

    • changes the current field number
      */
      FForm.prototype._updateFieldNumber = function() {
      if( this.options.ctrlNavPosition ) {
      // first, create next field number placeholder
      this.ctrlFldStatusNew = document.createElement( ‘span’ );
      this.ctrlFldStatusNew.className = ‘fs-number-new’;
      this.ctrlFldStatusNew.innerHTML = Number( this.current + 1 );

       // insert it in the DOM
       this.ctrlFldStatus.appendChild( this.ctrlFldStatusNew );
       
       // add class "fs-show-next" or "fs-show-prev" depending on the navigation direction
       var self = this;
       setTimeout( function() {
       	classie.add( self.ctrlFldStatus, self.navdir === 'next' ? 'fs-show-next' : 'fs-show-prev' );
       }, 25 );
      

      }
      }

    /**

    • progress function
    • updates the progress bar by setting its width
      */
      FForm.prototype._progress = function() {
      if( this.options.ctrlProgress ) {
      this.ctrlProgress.style.width = this.current * ( 100 / this.fieldsCount ) + ‘%’;
      }
      }

    /**

    • updateNav function
    • updates the navigation dots
      */
      FForm.prototype._updateNav = function() {
      if( this.options.ctrlNavDots ) {
      classie.remove( this.ctrlNav.querySelector( ‘button.fs-dot-current’ ), ‘fs-dot-current’ );
      classie.add( this.ctrlNavDots[ this.current ], ‘fs-dot-current’ );
      this.ctrlNavDots[ this.current ].disabled = false;
      }
      }

    /**

    • showCtrl function
    • shows a control
      */
      FForm.prototype._showCtrl = function( ctrl ) {
      classie.add( ctrl, ‘fs-show’ );
      }

    /**

    • hideCtrl function
    • hides a control
      */
      FForm.prototype._hideCtrl = function( ctrl ) {
      classie.remove( ctrl, ‘fs-show’ );
      }

    // TODO: this is a very basic validation function. Only checks for required fields…
    FForm.prototype._validade = function() {
    var fld = this.fields[ this.current ],
    input = fld.querySelector( ‘input[required]’ ) || fld.querySelector( ‘textarea[required]’ ) || fld.querySelector( ‘select[required]’ ),
    error;

     if( !input ) return true;
    
     switch( input.tagName.toLowerCase() ) {
     	case 'input' : 
     		if( input.type === 'radio' || input.type === 'checkbox' ) {
     			var checked = 0;
     			[].slice.call( fld.querySelectorAll( 'input[type="' + input.type + '"]' ) ).forEach( function( inp ) {
     				if( inp.checked ) {
     					++checked;
     				}
     			} );
     			if( !checked ) {
     				error = 'NOVAL';
     			}
     		}
     		else if( input.value === '' ) {
     			error = 'NOVAL';
     		}
     		break;
    
     	case 'select' : 
     		// assuming here '' or '-1' only
     		if( input.value === '' || input.value === '-1' ) {
     			error = 'NOVAL';
     		}
     		break;
    
     	case 'textarea' :
     		if( input.value === '' ) {
     			error = 'NOVAL';
     		}
     		break;
     }
    
     if( error != undefined ) {
     	this._showError( error );
     	return false;
     }
    
     return true;
    

    }

    // TODO
    FForm.prototype._showError = function( err ) {
    var message = ‘’;
    switch( err ) {
    case ‘NOVAL’ :
    message = ‘Please fill the field before continuing’;
    break;
    case ‘INVALIDEMAIL’ :
    message = ‘Please fill a valid email address’;
    break;
    // …
    };
    this.msgError.innerHTML = message;
    this._showCtrl( this.msgError );
    }

    // clears/hides the current error message
    FForm.prototype._clearError = function() {
    this._hideCtrl( this.msgError );
    }

    // add to global namespace
    window.FForm = FForm;

})( window );

Did you ever get this to work?