0

I am trying to apply a solution described here: Prevent body from scrolling on mouswheel, but not the texarea to textareas which are editable by CKEditor.

I tried to add the following code to the bottom of config.js and styles.js

$( document ).ready(function() {
  debugger;
  $('.cke_editable')
    .bind('mousewheel', function(event, delta) {
      if (this.scrollHeight && this.scrollHeight <= $(this).height() + $(this).scrollTop() && delta < 0){
        event.preventDefault()
      } else if($(this).scrollTop()===0 &&  delta > 0){
        event.preventDefault()
      }
    });
});

But the scrolling doesn't change and I think the code doesn't run at all (e.g. it doesn't break on debugger).

I've no clue about the other solution (wrapping content inside <body> tag), looks like some hacking would be necessary to apply to CKEditor.

[Edit]

After including code from the accepted answer and after further experimenting with CKEditor on my Drupal site, this is the code that finally works:

   CKEDITOR.on('instanceReady', function(ev) {
      var $iframe = jQuery('.cke').find('iframe');
      $iframe
        .bind('mousewheel', function(event, delta) {
          if (this.scrollHeight && this.scrollHeight <= jQuery(this).height() + jQuery(this).scrollTop() && delta < 0){
            event.preventDefault()
          } else if(jQuery(this).scrollTop()===0 &&  delta > 0){
            event.preventDefault()
          }
        });
    });

It still has one problem, after changing edit mode to "Source" and then back to wysiwyg, the binding is lost. It probably needs re-binding on yet another CKEditor event. I tried CKEDITOR.on('mode', function(ev) {... following this post, but it didn't fire. If I find a solution I'll update.

By the way, here is my CKEditor fiddle with this problem: http://jsfiddle.net/67v3rwfo/

[Edit 2]

I noticed that the fiddle works only in Chrome. In Firefox and IE it scrolls the window anyway, even without changing to "Source".

Community
  • 1
  • 1
camcam
  • 2,585
  • 8
  • 49
  • 65

1 Answers1

0

Are you sure that .cke_editable exists during the document ready event? I'm guessing that even though CKE init is quite fast they only appear after .ready. Try something like this

CKEDITOR.on('instanceReady', function(ev) {
    alert("InstanceReady");
    // $('.cke_editable')... here
});

$(document).ready(function() {
    alert(1);
});

Using alert makes sure that the code does get hit, even if the debugger is somehow derping out on you. If you never see the alert(1); it is very likely that some javascript is actually broken, because that code is unrelated to CKEditor. Check your Developer console for messages during page loading.


Edit 10.9.2014

Not sure if this helps with the underlying issue, but to target the .cke_editable element(s) in an iframe, this seems to work:

var iframeDocument = $('.cke').find('iframe').contents();
var editable = $(iframeDocument).find('.cke_editable');
// editable is like [<body contenteditable=​"true" ​…>​…​</body>​]
Joel Peltonen
  • 13,025
  • 6
  • 64
  • 100
  • With your improvement, the alert on "instanceReady" pops up. However, just after the alert, the selector jQuery('.cke_editable') is empty, and so the binding doesn't take place. I suspect that it is because CKEditor creates a document inside document. So in the main HTML document (where CKE config.js is loaded), there is a div of class "cke". After CKE initialization, this div contains another #document, with html and body tags. The inner body has class '.cke_editable' and is directly editable (no textarea inside). I think it's not visible for the outer javascript. – camcam Sep 09 '14 at 16:06
  • I edited an example to reference the editable inside an iframe, but I'm not sure if that will help with the scrolling issue. At least you can target it. Note that this only works if the iframe does not violate cross domain policy, but I think it's very likely to work with CKE. – Joel Peltonen Sep 10 '14 at 05:32
  • This works, thanks! In my case, it was also necessary to change the mousewheel binding target. It should not be cke_editable, because it's as high as its current contents, no matter what the size of the iframe. The binding target should be the iframe itself.. I'll update my original code with it. One problem is still left, the binding is lost after changing mode to "Source" and then back, that's probably about finding yet another CKEditor event. – camcam Sep 10 '14 at 07:43
  • Yeah, I think that might be the way to solve that issue :) Glad to hear it works! – Joel Peltonen Sep 11 '14 at 06:02