Streaming live at 10am (PST)

Custom Code Integration


#1

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!


#2

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?


#3

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 );


#4

Did you ever get this to work?