jQuery $ .fn不是一个函数

时间:2016-09-18 20:09:42

标签: javascript jquery

直接投票?

我是否遗漏了$.fn.无效的任何内容。虽然我有其他模块,但这个功能就像魅力一样。

我在jQuery中遇到了一些奇怪的错误。我正在使用jquery.jrac.js文件裁剪图片,不幸的是我在访问函数时得到TypeError: $.fn.jracIMG is not a function $.fn.jracIMG("", param);

我已正确添加了jquery.js文件。

如果我从$.fn.中移除jracIMG,则在库文件本身中会出现其他一些奇怪的错误,例如$(elem).find("img").jrac({

以下是我正在使用的功能

    (function( $ ){

  $.fn.jrac = function(options) {

    // Default settings
    var settings = {
      'crop_width': 200,
      'crop_height': 100,
      // The two following properties define the crop position (relative to the
      // image).
      'crop_x': 0,
      'crop_y': 0,
      'crop_resize': true,
      'crop_aspect_ratio': null,
      'image_width': null,
      'image_height': null,
      'zoom_min': 100,
      'zoom_max': 3000,
      'zoom_label': '',
      'viewport_image_surrounding': false, // Set the viewport to surround the image on load
      'viewport_width': null,
      'viewport_height': null,
      'viewport_resize': true,
      // The two following properties allow to position the content (negative
      // value allowed). It can be use to focus the viewport on the cropped
      // part of the image.
      'viewport_content_left': 0,
      'viewport_content_top': 0,
      // Submit here a callback function (context is the viewport).
      'viewport_onload': null
    };

    // Apply the resize and crop tools to each images
    return this.each(function() {

      if (!$(this).is('img')) {
        return;
      }

      // Read options
      var destroy = false;
      if ( typeof(options) == 'object' ) {
        $.extend( settings, options );
      }
      else if (options == 'destroy') {
        destroy = true;
      }

      var $image = $(this);

      // Test if jrac was previously run
      var jrac_loaded = false;
      if ($image.parent().hasClass('jrac_viewport')) {
        jrac_loaded = true;
      }

      if (jrac_loaded && destroy) {
        // Unload jrac if asked
        $image.draggable("destroy");
        $image.parent().find('.jrac_crop').remove();
        $image.parent().parent().find('.jrac_zoom_slider').remove();
        $image.parent().append($image.data('original')); // restore original image
        $image.parent().unwrap(); // remove container
        $image.unwrap(); // remove viewport
        $image.remove(); // remove image which was altered (in its css attributes)
      }
      else {
        // Record image before some of its attributes get altered by some
        // jrac css or some user size or proportion changes.
        $image.data('original', $image.clone());
      }

      // Do nothing more if destroy is asked
      if (destroy) {
        return;
      }

      // Prepare image
      if (!jrac_loaded) {
        $image.hide().css('position','absolute').wrap('<div class="jrac_container"><div class="jrac_viewport"></div></div>');
      }

      // Get viewport and container references
      var $viewport = $image.parent();
      var $container = $viewport.parent();

      // Add a waiting on load input image
      var $loading = $('<div class="jrac_loading" />');
      $viewport.append($loading);

      // The following procedure hold business intend to be run once the image
      // is loaded (load event).
      var image_load_handler = function(){

        // Add some custom properties to $image
        $.extend($image, {
          scale_proportion_locked: true,
          originalWidth: $image.width(),
          originalHeight: $image.height()
        });

        // Set given optional image size
        $image.width(settings.image_width).height(settings.image_height);

        // Apply the viewport image surrounding is asked
        if (settings.viewport_image_surrounding) {
          $viewport.width($image.width()).height($image.height());
        }
        else {
          $viewport.width(settings.viewport_width).height(settings.viewport_height);
        }

        // Set the viewport content position for the image
        $image.css({'left': settings.viewport_content_left, 'top': settings.viewport_content_top});

        // Create the zoom widget which permit to resize the image
        if (!jrac_loaded) {
          if (settings.zoom_label) {
              var $zoom_label = $('<div class="jrac_zoom_slider_label">'+settings.zoom_label+'</div>');
              $container.append($zoom_label);
          }
          var $zoom_widget = $('<div class="jrac_zoom_slider"><div class="ui-slider-handle"></div></div>')
          .slider({
            value: $image.width(),
            min: settings.zoom_min,
            max: settings.zoom_max,
            start: function(event, ui) {
              $.extend($zoom_widget,{
                on_start_width_value: ui.value,
                on_start_height_value: $image.height()
              })
            },
            slide: function(event, ui) {
              var height = Math.round($zoom_widget.on_start_height_value * ui.value / $zoom_widget.on_start_width_value);
              $image.height(height);
              $image.width(ui.value);
              $viewport.observator.notify('jrac_image_height', height);
              $viewport.observator.notify('jrac_image_width', ui.value);
            }
          });
          $container.append($zoom_widget);

          // Make the viewport resizeable
          if (settings.viewport_resize) {
            $viewport.resizable();
          }

          // Enable the image draggable interaction
          $image.draggable({
            drag: function(event, ui) {
              if (ui.position.left != ui.originalPosition.left) {
                $viewport.observator.notify('jrac_crop_x', $viewport.observator.crop_position_x());
              }
              if (ui.position.top != ui.originalPosition.top) {
                $viewport.observator.notify('jrac_crop_y', $viewport.observator.crop_position_y());
              }
            }
          });

          // Build the crop element
          var $crop = $('<div class="jrac_crop"><div class="jrac_crop_drag_handler"></div></div>')
          .css({
            'width': settings.crop_width,
            'height': settings.crop_height,
            'left':settings.crop_x+settings.viewport_content_left,
            'top':settings.crop_y+settings.viewport_content_top
          }).draggable({
            containment: $viewport,
            handle: 'div.jrac_crop_drag_handler',
            drag: function(event, ui) {
              if (ui.position.left != ui.originalPosition.left) {
                $viewport.observator.notify('jrac_crop_x', $viewport.observator.crop_position_x());
              }
              if (ui.position.top != ui.originalPosition.top) {
                $viewport.observator.notify('jrac_crop_y', $viewport.observator.crop_position_y());
              }
            }
          });
          if (settings.crop_resize) {
            $crop.resizable({
              containment: $viewport,
              aspectRatio: settings.crop_aspect_ratio,
              resize: function(event, ui) {
                if (ui.size.width != ui.originalSize.width) {
                  $viewport.observator.notify('jrac_crop_width', $crop.width());
                }
                if (ui.size.height != ui.originalSize.height) {
                  $viewport.observator.notify('jrac_crop_height', $crop.height());
                }
              }
            })
          }
          $viewport.append($crop);
        }

        // Extend viewport witch usefull objects as it will be exposed to user
        // functions interface
        $.extend($viewport, {
          $container: $container,
          $image: $image,
          $crop: $crop,
          $zoom_widget: $zoom_widget,
          // Let me introduce the following Terminator's friend which handle the
          // creation of the viewport events.
          observator: {
            items: {},
            // Register an event with a given element
            register: function(event_name, element, onevent_callback) {
              if (event_name && element) {
                this.items[event_name] = {
                  element: element,
                  callback: onevent_callback
                };
              }
            },
            // Unregister an event
            unregister: function(event_name) {
              delete this.items[event_name];
            },
            // Trigger an event and optionally supply a value
            notify: function(event_name, value) {
              if (this.items[event_name]) {
                var element = this.items[event_name].element;
                var onevent_callback = this.items[event_name].callback;
                element.trigger(event_name,[$viewport, value]);
                if ($.isFunction(onevent_callback)) {
                  onevent_callback.call($viewport, event_name, element, value);
                }
              }
              $image.trigger('jrac_events',[$viewport]);
            },
            notify_all: function() {
              this.notify('jrac_crop_x', this.crop_position_x());
              this.notify('jrac_crop_y', this.crop_position_y());
              this.notify('jrac_crop_width', $crop.width());
              this.notify('jrac_crop_height', $crop.height());
              this.notify('jrac_image_width', $image.width());
              this.notify('jrac_image_height', $image.height());
            },
            // Return crop x position relative to $image
            crop_position_x: function() {
              return $crop.position().left - $image.position().left;
            },
            // Return crop y position relative to $image
            crop_position_y: function() {
              return $crop.position().top - $image.position().top;
            },
            // Does the crop is completely inside the image?
            crop_consistent: function() {
              return this.crop_position_x()>=0 && this.crop_position_y()>=0
              && this.crop_position_x() + $crop.width() + parseInt($crop.css('border-width'),10)*2  <=$image.width()
              && this.crop_position_y() + $crop.height() + parseInt($crop.css('border-width'),10)*2 <=$image.height();
            },
            // Set a property (which his name is one of the event) with a given
            // value then notify this operation
            set_property: function(that, value) {
              value = parseInt(value);
              if (isNaN(value)) {
                return;
              }
              switch (that) {
                case 'jrac_crop_x':
                  $crop.css('left',value + $image.position().left);
                  break;
                case 'jrac_crop_y':
                  $crop.css('top',value + $image.position().top);
                  break;
                case 'jrac_crop_width':
                  $crop.width(value);
                  break;
                case 'jrac_crop_height':
                  $crop.height(value);
                  break;
                case 'jrac_image_width':
                  if ($image.scale_proportion_locked) {
                    var image_height = Math.round($image.height() * value / $image.width());
                    $image.height(image_height);
                    this.notify('jrac_image_height', image_height);
                  }
                  $image.width(value);
                  $zoom_widget.slider('value', value);
                  break;
                case 'jrac_image_height':
                  if ($image.scale_proportion_locked) {
                    var image_width = Math.round($image.width() * value / $image.height());
                    $image.width(image_width);
                    this.notify('jrac_image_width', image_width);
                    $zoom_widget.slider('value', image_width);
                  }
                  $image.height(value);
                  break;
              }
              this.notify(that, value);
            }
          }
        });

        // Hide the loading notice
        $loading.hide();
        $loading.remove();

        // Finally display the image
        $image.show();

        // Trigger the viewport_onload callback
        if ($.isFunction(settings.viewport_onload)) {
          settings.viewport_onload.call($viewport);
          $viewport.observator.notify_all();
        }
      };

      // When an image is using an src image "data" URL scheme then it appear
      // that the image load event never get fired. Then fire directly
      // image_load_handler() in that case.
      var src = $image.attr('src');
      if (/^data:image/.test(src)) {
         image_load_handler();
      }
      else {
        src = src + (src.search(/\?/)<0?'?':'&') + 'jracrandom=' + (new Date()).getTime();
        $('<img>').attr('src', src).load(image_load_handler);
      }
    });
  };
})( jQuery );

这个

$.fn.jracIMG = function(elem,param) {
        $(elem).find("img").jrac({
            'crop_resize':param["crop_resize"],
            'viewport_resize': param["viewport_resize"],
            'crop_width': param["crop_width"],
            'crop_height': param["crop_height"],
            'crop_x': param["crop_x"],
            'crop_y': param["crop_y"],
            'image_width' : param["image_width"] ? param["image_width"] : 550,
            'viewport_onload': function() {            
                var $viewport = this;
                //$viewport.$image.draggable("destroy");
                var inputs = $viewport.$container.parent('.pane').find('.coords input:hidden');

                var events = ['jrac_crop_x', 'jrac_crop_y', 'jrac_crop_width', 'jrac_crop_height', 'jrac_image_width', 'jrac_image_height'];
                for (var i = 0; i < events.length; i++) {
                    var event_name = events[i];
                    // Register an event with an element.
                    $viewport.observator.register(event_name, inputs.eq(i));
                    // Attach a handler to that event for the element.
                    inputs.eq(i).bind(event_name, function(event, $viewport, value) {
                        $(this).val(value);
                    })
                            // Attach a handler for the built-in jQuery change event, handler
                            // which read user input and apply it to relevent viewport object.
                            .change(event_name, function(event) {
                                var event_name = event.data;
                                $viewport.$image.scale_proportion_locked = $viewport.$container.parent('.pane').find('.coords input:checkbox').is(':checked');
                                $viewport.observator.set_property(event_name, $(this).val());
                            });
                }
                $viewport.$container.find(".imgnatsize").remove();
                $viewport.$container.append('<div class=imgnatsize>Image natual size: '
                        + $viewport.$image.originalWidth + ' x '
                        + $viewport.$image.originalHeight + '</div>')
            }
        })
                // React on all viewport events.
                .bind('jrac_events', function(event, $viewport) {
                    var inputs = $(this).parents('.pane').find('.coords input');
                    //inputs.css('background-color', ($viewport.observator.crop_consistent()) ? 'chartreuse' : 'salmon');
                    if ($viewport.observator.crop_consistent()) {
                        inputs.removeClass('_err').addClass('_suc');
                    } else {
                        inputs.removeClass('_suc').addClass('_err');
                    }
                });


    }
    $.fn.containerFix = function(container) {
         container = $(container);
        var mTop = container.outerHeight() / 2;
        container.css({
            'margin-top': -mTop,
        });
    };

    $.fn.createCropPanel = function() {
        var elem;
        elem = "<div class='pane clearfix'>";
        elem += "<img class='cropPreview' />";
        elem += "<form class='cropPanelForm' method='post'>";
        elem += "<div class='coords'>";
        elem += "<input type='hidden'  name='cropx'/>";
        elem += "<input type='hidden'  name='cropy'/>";
        elem += "<input type='hidden'  name='cropw'/>";
        elem += "<input type='hidden'  name='croph'/>";
        elem += "<input type='hidden'  name='imagew'/>";
        elem += "<input type='hidden'  name='imageh'/>";
        elem += "<input type='hidden'  name='imagefilename'/>";
        elem += "<input type='hidden'  name='imagefiledirectory'/>";
        elem += "<input type='hidden'  name='is_dashboard' value='0'/>";
        elem += "<input type='submit' value='Crop & Save' class='btn-cta btn-cta-sm b-styled' />";
        elem += "<input type='hidden'  name='logofilename'/>";
        elem += "<input type='hidden'  name='logofiledirectory'/>";
        elem += "<input type='hidden'  name='sliderfilename'/>";
        elem += "<input type='hidden'  name='sliderfiledirectory'/>";
        elem += "</div>";
        elem += "</form>";
        elem += "</div>";
        return elem;
    };

$.fn.createCropPanelOnboard = function() {
    var elem;
    elem = "<div class='pane clearfix'>";
    elem += "<img class='cropPreview' />";
    elem += "<form class='cropPanelForm' method='post'>";
    elem += "<div class='coords'>";
    elem += "<input type='hidden'  name='cropx'/>";
    elem += "<input type='hidden'  name='cropy'/>";
    elem += "<input type='hidden'  name='cropw'/>";
    elem += "<input type='hidden'  name='croph'/>";
    elem += "<input type='hidden'  name='imagew'/>";
    elem += "<input type='hidden'  name='imageh'/>";
    elem += "<input type='hidden'  name='imagefilename'/>";
    elem += "<input type='hidden'  name='imagefiledirectory'/>";
    elem += "<input type='hidden'  name='is_dashboard' value='0'/>";
    //elem += "<input type='submit' id='crop_btn' value='Crop & Save' class='btn-cta btn-cta-sm b-styled' />";
    elem += "<a href='javascript:;' class='btn-cta btn-cta-sm b-styled' id='crop_btn' >Crop & Save</a>";
        elem += "<input type='hidden'  name='logofilename'/>";
    elem += "<input type='hidden'  name='logofiledirectory'/>";
    elem += "<input type='hidden'  name='sliderfilename'/>";
    elem += "<input type='hidden'  name='sliderfiledirectory'/>";
    elem += "</div>";
    elem += "</form>";
    elem += "</div>";
    return elem;
};

任何帮助都将不胜感激。

解决方案

我将这些功能定义放在

$(document).ready(function(){
   //Both files code goes here
});

现在它的工作就像一个魅力。

2 个答案:

答案 0 :(得分:0)

过去我遇到过同样的问题,您是否尝试过使用CDN而不是自己托管代码?
我建议使用谷歌的CDN,因为他们拥有非常快的服务器,并且不会减慢客户端的速度。您并使用<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>代替您的文件。
我希望这会对你有所帮助。

答案 1 :(得分:0)

我将这些函数定义,函数放在

中的文件中
$(document).ready(function(){
   //Both files code goes here
});

现在它的工作就像一个魅力。