closedquestion-8.x-3.x-dev/assets/js/closedquestion_hs.js

assets/js/closedquestion_hs.js
/**
 *@file
 *Javascript functions for the Hotspot questions.
 */

/**
 * Generate the answer string from the draggables, for the question with the
 * given id and puts it in the answer form field for that question.
 *
 * @param questionId string
 *   The question id of the question to generate the answer string for.
 *
 * @return TRUE
 */
function cqCheckAnswerHS(questionId) {
  var returnString = "";
  var qsettings = drupalSettings.closedQuestion.hs[questionId];
  var length = qsettings.ddDraggableStartPos.length;
  var i;
  for (i = 0; i < length; i++) {
    var draggableVar = qsettings.ddDraggableStartPos[i];
    returnString += "" + draggableVar.cqvalue + "," + draggableVar.x + "," + draggableVar.y + ";";
  }

  var answerElement = jQuery('[name="' + questionId + 'answer"]');
  answerElement.val(returnString);
  return true;
}

(function ($) {
  /**
   * Attach the code that puts all draggables in the right spot, and loads
   * the dragArea to a Drupal behaviour.
   */

  Drupal.behaviors.closedQuestionHS = {
    "attach": function (context) {
      var settings = drupalSettings.closedQuestion.hs;

      for (var questionId in settings) {
        /* init */
        var qsettings = settings[questionId];
        if (qsettings['initialised']) {
          continue;
        }
        qsettings['initialised'] = true;

        if (context === document) {
          // Bind to plugin add and remove events to keep track of the answer.
          $('#' + questionId + 'answerContainer').bind('CQHotspot.addDot', function (e, byGUI) {
            if (byGUI === true) {
              var hsPlugin = $('#' + questionId + 'answerContainer').data('CQHotspot');
              drupalSettings.closedQuestion.hs[questionId].ddDraggableStartPos = hsPlugin.getDots();
            }

            // Update answer for server.
            cqCheckAnswerHS(questionId);
          });

          $('#' + questionId + 'answerContainer').bind('CQHotspot.removeDot', function (e, byGUI) {
            if (byGUI === true) {
              if (byGUI === true) {
                var hsPlugin = $('#' + questionId + 'answerContainer').data('CQHotspot');
                drupalSettings.closedQuestion.hs[questionId].ddDraggableStartPos = hsPlugin.getDots();
              }

              // Update answer for server.
              cqCheckAnswerHS(questionId);
            }
          });

          // Start the engine.
          $('#' + questionId + 'answerContainer').CQHotspot(qsettings);
        }
      }
    }
  };

  /**
   * CQHotspot
   * based on boilerplate version 1.3
   * @param {object} $ A jQuery object
   **/
  $.CQHotspot = function (element, settings) {

    /* define vars
     */

    /* this object will be exposed to other objects */
    var publicObj = this;

    //the version number of the plugin
    publicObj.version = '1.0';

    /* this object holds functions used by the plugin boilerplate */
    var _helper = {
      /**
       * Call hooks, additinal parameters will be passed on to registered plugins
       * @param {string} name
       */
      "doHook": function (name) {
        var i;
        var returnValue = true;
        var pluginFunctionArgs = [];

        /* remove first two arguments */
        for (i = 1; i < arguments.length; i++) {
          pluginFunctionArgs.push(arguments[i]);
        }

        /* call plugin functions */
        if (_globals.plugins !== undefined) {
          /* call plugins */
          $.each(_globals.plugins, function (_, extPlugin) {
            if (extPlugin.__hooks !== undefined && extPlugin.__hooks[name] !== undefined) {
              returnValue = (returnValue === false || extPlugin.__hooks[name].apply(publicObj, pluginFunctionArgs) === false) ? false : true;
            }
          });
        }

        /* trigger event on main element */
        returnValue = (returnValue === false || _globals.$element.triggerHandler('CQHotspot.' + name, pluginFunctionArgs) === false) ? false : true;

        return returnValue;
      },
      /**
       * Initializes the plugin
       */
      "doInit": function () {
        _helper.doHook('CQHotspot.beforeInit', publicObj, element, settings);
        publicObj.init();
        _helper.doHook('CQHotspot.init', publicObj);
      },
      /**
       * Loads an external script
       * @param {string} libName
       * @param {string} errorMessage
       */
      "loadScript": function (libName, errorMessage) {
        /* remember libname */
        _cdnFilesToBeLoaded.push(libName);

        /* load script */
        $.ajax({
          "type": "GET",
          "url": _globals.dependencies[libName].cdnUrl,
          "success": function () {
            /* forget libname */
            _cdnFilesToBeLoaded.splice(_cdnFilesToBeLoaded.indexOf(libName), 1); //remove element from _cdnFilesToBeLoaded array

            /* call init function when all scripts are loaded */
            if (_cdnFilesToBeLoaded.length === 0) {
              _helper.doInit();
            }
          },
          "fail": function () {
            console.error(errorMessage);
          },
          "dataType": "script",
          "cache": "cache"
        });
      },
      /**
       * Registers a plugin
       * @param {string} name Name of plugin, must be unique
       * @param {object} object An object {("functions": {},) (, "hooks: {})}
       */
      "registerPlugin": function (name, object) {
        var plugin;
        var hooks;

        /* reorder plugin */
        hooks = $.extend(true, {}, object.hooks);
        plugin = object.functions !== undefined ? object.functions : {};
        plugin.__hooks = hooks;

        /* add plugin */
        _globals.plugins[name] = plugin;
      },
      /**
       * Calls a plugin function, all additional arguments will be passed on
       * @param {string} CQHotspot
       * @param {string} pluginFunctionName
       */
      "callPluginFunction": function (CQHotspot, pluginFunctionName) {
        var i;

        /* remove first two arguments */
        var pluginFunctionArgs = [];
        for (i = 2; i < arguments.length; i++) {
          pluginFunctionArgs.push(arguments[i]);
        }

        /* call function */
        _globals.plugins[CQHotspot][pluginFunctionName].apply(null, pluginFunctionArgs);
      },
      /**
       * Checks dependencies based on the _globals.dependencies object
       * @returns {boolean}
       */
      "checkDependencies": function () {
        var dependenciesPresent = true;
        for (var libName in _globals.dependencies) {
          var errorMessage = 'jquery.CQHotspot: Library ' + libName + ' not found! This may give unexpected results or errors.';
          var doesExist = $.isFunction(_globals.dependencies[libName]) ? _globals.dependencies[libName] : _globals.dependencies[libName].doesExist;
          if (doesExist.call() === false) {
            if ($.isFunction(_globals.dependencies[libName]) === false && _globals.dependencies[libName].cdnUrl !== undefined) {
              /* cdn url provided: Load script from external source */
              _helper.loadScript(libName, errorMessage);
            }
            else {
              console.error(errorMessage);
              dependenciesPresent = false;
            }
          }
        }
        return dependenciesPresent;
      }
    };
    /* keeps track of external libs loaded via their CDN */
    var _cdnFilesToBeLoaded = [];

    /* this object holds all global variables */
    var _globals = {};

    _globals.dotsIdPrefix = 'cqHotspotDot_' + $(element).attr('id') + '_';

    /* keep track of dots */
    _globals.dotCounter = 0;

    /* handle settings */
    var defaultSettings = {
      "dotSize": 10
    };

    _globals.settings = {};

    if ($.isPlainObject(settings) === true) {
      _globals.settings = $.extend(true, {}, defaultSettings, settings);
    }
    else {
      _globals.settings = defaultSettings;
    }

    /* this object contains a number of functions to test for dependencies,
     * doesExist function should return TRUE if the library/browser/etc is present
     */
    _globals.dependencies = {
      /* check for jQuery 1.6+ to be present */
      "jquery1.6+": {
        "doesExist": function () {
          var jqv, jqv_main, jqv_sub;
          if (window.jQuery) {
            jqv = jQuery().jquery.split('.');
            jqv_main = parseInt(jqv[0], 10);
            jqv_sub = parseInt(jqv[1], 10);
            if (jqv_main > 1 || (jqv_main === 1 && jqv_sub >= 6)) {
              return true;
            }
          }
          return false;
        },
        "cdnUrl": "http://code.jquery.com/jquery-git1.js"
      }
    };
    _helper.checkDependencies();

    //this object holds all plugins
    _globals.plugins = {};


    /* register DOM elements
     * jQuerified elements start with $
     */
    _globals.$element = $(element);

    /**
     * Init function
     **/
    publicObj.init = function () {
      _globals.$element.addClass('cqHotspot');
      _globals.$image = _globals.$element.find('img');
      _globals.$imagemap = _globals.$element.find('map');


      /* create container and fill it with elements
       */
      _globals.$imageContainer = $('<div class="cqHotspotImageContainer" />');
      _globals.$imageContainer.insertBefore(_globals.$image);

      _globals.$imageContainer.append(_globals.$image, _globals.$imagemap);

      //click event
      _globals.$imageContainer.on('click', onImageClick);

      //init hotspot images
      initHotspotImages();

      //load dots
      publicObj.setDots(_globals.settings.ddDraggableStartPos);

      //listen to feedback updates
      $('body').bind('closedquestion.onUpdateFeedback', handleFeedback);
      handleFeedback();
    };

    /**
     * Adds dots to image.
     *
     * @param {array} dotsData
     *   Array containing {"x": <int>, "y": <int>} objects.
     */
    publicObj.setDots = function (dotsData) {
      $.each(dotsData, function (i) {
        var dotData = dotsData[i];

        addDot(dotData.x, dotData.y);
      });
    };

    /**
     * Returns all current dots.
     *
     * @returns {array}
     *   Array containing {"x": <int>, "y": <int>, "cqvalue": <string>} objects.
     */
    publicObj.getDots = function () {
      var dotsData = [];
      // Get all dots from DOM.
      $('.cqHotspotDot', _globals.$element).each(function () {
        var $hs = $(this);
        var hsPosition = $hs.position();
        var id = $hs.data(_globals.dotsIdPrefix);

        // Add element to dotsData.
        dotsData.push({
          "x": Math.round(hsPosition.left),
          "y": Math.round(hsPosition.top),
          "cqvalue": 'd' + id
        });
      });

      return dotsData;
    }


    /**
     * Registers a plugin
     * @param {string} name Name of plugin, must be unique
     * @param {object} object An object {("functions": {},) (, "hooks: {}) (, "targetCQHotspots": [])}
     */
    publicObj.registerPlugin = function (name, object) {
      _helper.registerPlugin(name, object);
    };

    /**
     * Calls a plugin function, all additional arguments will be passed on
     * @param {string} CQHotspot
     * @param {string} pluginFunctionName
     */
    publicObj.callPluginFunction = function (CQHotspot, pluginFunctionName) {
      /* call function */
      _helper.callPluginFunction.apply(null, arguments);
    };

    function handleFeedback() {
      var $newImage = $('.cq-feedback-wrapper img.cqImageFeedback');

      if ($newImage.length === 1) {
        _globals.$image.attr('src', $newImage.attr('src'));
        $newImage.remove();

        $('.cqHotspotHoverImage, .cqHotspotSelectImage').remove(); //remove hover images
      }
    }

    /**
     * Inits the hotspot hover and select images;
     */
    function initHotspotImages() {
      var $areas = _globals.$imagemap.find('area');
      $areas.each(function () {
        var $area = $(this);
        var id = $area.attr('id');
        var imagesData = _globals.settings.hotspotImages[id];
        if (imagesData['hover']) {
          $area.bind('mouseover', function () {
            var $area = $(this);
            var id = $area.attr('id');
            var coords, $hImage;
            coords = $area.attr('coords').split(',');
            // Prevent duplicate hover images.
            $('.cqHotspotHoverImage#cqHotspotHoverImage_' + id).remove();
            $hImage = $('<img class="cqHotspotHoverImage" id="cqHotspotHoverImage_' + id + '" src="' + imagesData['hover']['url'] + '" />');

            _globals.$imageContainer.append($hImage);
            $hImage.css({
              "position": "absolute",
              "top": (parseInt(coords[1], 10) + parseInt(imagesData['hover']['offset'][1], 10)) + 'px',
              "left": (parseInt(coords[0], 10) + parseInt(imagesData['hover']['offset'][0], 10)) + 'px',
              "border": "1px solid transparent"
            });

            $hImage.bind('mouseout', function () {
              $(this).remove();
            });
          });
          $area.bind('mouseout', function (event) {
            var $area = $(this);
            var id = $area.attr('id');
            var $hImage = $('.cqHotspotHoverImage#cqHotspotHoverImage_' + id);
            // Remove hover image if it is not the relatedTarget.
            if (event.relatedTarget.id !== $hImage.get(0).id) {
              $hImage.remove();
            }
          });
        }

        if (imagesData['select']) {
          $area.bind('onadddot', function () {
            var $area = $(this);
            var id = $area.attr('id');
            var coords, $hImage;
            coords = $area.attr('coords').split(',');
            $hImage = $('<img class="cqHotspotSelectImage" id="cqHotspotSelectImage_' + id + '" src="' + imagesData['select']['url'] + '" />');

            _globals.$imageContainer.append($hImage);
            $hImage.css({
              "position": "absolute",
              "top": (parseInt(coords[1], 10) + parseInt(imagesData['select']['offset'][1], 10)) + 'px',
              "left": (parseInt(coords[0], 10) + parseInt(imagesData['select']['offset'][0], 10)) + 'px',
              "border": "1px solid transparent"
            });
          });
        }
      });
    }

    /**
     * Determines whether a point is inside an area
     *
     * @param {object} $area
     * @param {int} x
     * @param {int} y
     * @returns {Boolean}
     */
    function isPointInArea(x, y, $area) {
      var c = false;
      var m, poly, pt, numberOfCoords;
      var shape = $area.attr('shape');
      var coords = $area.attr('coords').split(',');

      if (shape === 'rect' || shape === 'poly') {
        poly = [];
        pt = {"x": parseInt(x, 10), "y": parseInt(y, 10)};

        /* get rectangle or polygon coordinates */
        if (shape === 'rect') {
          //x1,y1,x2,y2
          //0  1  2  3

          poly.push({"x": parseInt(coords[0], 10), "y": parseInt(coords[1], 10)}); //x1,y1
          poly.push({"x": parseInt(coords[2], 10), "y": parseInt(coords[1], 10)}); //x2,y1
          poly.push({"x": parseInt(coords[2], 10), "y": parseInt(coords[3], 10)}); //x2,y2
          poly.push({"x": parseInt(coords[0], 10), "y": parseInt(coords[3], 10)}); //x1,y2
          poly.push({"x": parseInt(coords[0], 10), "y": parseInt(coords[1], 10)});
        }
        else {
          numberOfCoords = coords.length;
          for (m = 0; m < numberOfCoords; m = m + 2) {
            poly.push({"x": parseInt(coords[m], 10), "y": parseInt(coords[m + 1], 10)});
          }
        }

        for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) {
          ((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y))
            && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x)
            && (c = !c);
        }
      }
      else {
        /* circle */
        c = Math.pow(x - coords[0], 2) + Math.pow(y - coords[1], 2) >= coords[2] * coords[2];
      }

      return c;
    }


    /**
     * Handles onclick event for image.
     *
     * @param {object} event
     * @returns {Boolean} false
     */
    function onImageClick(event) {
      var imageElement_offset = _globals.$imageContainer.offset();
      var correctedClientX = event.pageX - imageElement_offset.left - 4;
      var correctedClientY = event.pageY - imageElement_offset.top - 4;

      /* add dot */
      addDot(correctedClientX, correctedClientY, true);

      event.preventDefault();
      return false;
    }

    /**
     * Adds a dot
     * @param {integer} left
     * @param {integer} top
     * @param {boolean} byGUI True if GUI created dot (false by default)
     */
    function addDot(left, top, byGUI) {
      byGUI = byGUI === undefined ? false : byGUI;

      if (_globals.settings.maxChoices && _globals.settings.maxChoices !== "" && _globals.dotCounter === _globals.settings.maxChoices) {
        return;
      }
      var id = _globals.dotCounter;

      var $dotElement = $('<div id="' + _globals.dotsIdPrefix + id.toString() + '" class="cqHotspotDot"><div class="cqHotspotDotNumber" /></div>');

      $dotElement.data(_globals.dotsIdPrefix, id); //store its id
      /* add dot */
      _globals.$imageContainer.append($dotElement);
      if (byGUI === true) {
        $dotElement.addClass('big');
        $dotElement.css({
          "top": top - 30,
          "left": left - 30
        });

        $dotElement.animate({
          "top": top,
          "left": left,
          "width": _globals.settings.dotSize,
          "height": _globals.settings.dotSize
        }, {
          "duration": "fast",
          "complete": function () {
            $dotElement.css('overflow', '');
            $dotElement.removeClass('big');
            if (_globals.settings.clickOrder === "1") {
              updateNumbering();
            }
            _helper.doHook('addDot', byGUI);
          }
        });
      }
      else {
        $dotElement.css({
          "top": top,
          "left": left,
          "width": _globals.settings.dotSize,
          "height": _globals.settings.dotSize
        });
        updateNumbering();
      }

      // Make dot be removeable.
      $dotElement.on('click', function (event) {
        var id = $dotElement.data(_globals.dotsIdPrefix);
        removeDot(id, true);
        event.preventDefault();
        return false;
      });

      var $areas = _globals.$imagemap.find('area');
      $areas.each(function () {
        var cc;
        var $area = $(this);
        if (isPointInArea(left, top, $area) === true) {
          $area.trigger('onadddot');
          cc = $area.data('clickCount');
          cc = cc === undefined ? 1 : cc + 1;
          $area.data('clickCount', cc);
        }
      });

      _globals.dotCounter++;
    }

    /**
     * Updates the numbering of the dots.
     */
    function updateNumbering() {
      var number;
      if (_globals.settings.clickOrder === "1") {
        number = 1;
        _globals.$imageContainer.find('.cqHotspotDotNumber').each(function () {
          $(this).html(number);
          number++;
        });
      }
    }

    /**
     * Remove a dot
     * @param {integer} id Dot id
     * @param {boolean} byGUI True if GUI created dot (false by default)
     */
    function removeDot(id, byGUI) {
      byGUI = byGUI === undefined ? false : byGUI;
      var $dotElement = $('#' + _globals.dotsIdPrefix + id);
      $dotElement.addClass("removing")
      var position = $dotElement.position();

      $dotElement.animate({
        "top": position.top - 30,
        "left": position.left - 30,
        "width": 60,
        "height": 60,
        "opacity": 0
      },
        {
          "duration": "fast",
          "complete": function () {
            $dotElement.remove();

            if (_globals.settings.clickOrder === "1") {
              updateNumbering();
            }
            _helper.doHook('removeDot', byGUI);
          }
        });

      /* remove underlying hotspot image as well ? */
      var $areas = _globals.$imagemap.find('area');
      $areas.each(function () {
        var cc;
        var $area = $(this);
        if (isPointInArea(position.left, position.top, $area) === true) {
          cc = $area.data('clickCount');
          cc = cc === undefined ? 1 : cc - 1;
          $area.data('clickCount', cc);
          if (cc === 0) {
            $('#cqHotspotSelectImage_' + $area.attr('id')).remove();
          }
        }
      });
    }

    /* initialize CQHotspot
     */
    if (_cdnFilesToBeLoaded.length === 0) {
      _helper.doInit();
    }
  };

  $.fn.CQHotspot = function (settings) {
    return this.each(function () {
      if (undefined === $(this).data('CQHotspot')) {
        var plugin = new $.CQHotspot(this, settings);
        $(this).data('CQHotspot', plugin);
      }
    });
  };
})(jQuery);

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc