📜 ⬆️ ⬇️

Arrangement of points over onmousewheel and a little about onion soup

I already wrote about my experiments with scrollbars on websites and web applications, but these experiments were not entirely successful. Therefore, I have so far left the idea of ​​customizing scrollbars, but I decided to thoroughly understand the events caused by the scrolling of the mouse wheel.

So, the task is to implement a reaction to the mouse wheel scrolling events over a certain block, that is, without touching the browser's native window scroll. The implementation should be cross-browser and not use any frameworks.

Looking ahead, I will say that this experiment was completely successful, and the final result works in all desktop browsers, starting with IE7 (in theory, it should work in the sixth, but now there is no way to check it). Also, I want to thank Google search engine. Without it, life would be woven out of despondency and despair.

First, I solved the problem of catching onmousewheel for the entire window (the window object). It was decided so:
window.onload = function() {  if (window.addEventListener) window.addEventListener("DOMMouseScroll", mouse_wheel, false);  window.onmousewheel = document.onmousewheel = mouse_wheel; } 

The first line will catch the event in Firefox and the Whale web browsers (Chrome, Safari), the second is needed for catching in Opera and IE. The reaction to the event is the mouse_wheel () function, which looks like this for now:
 var mouse_wheel = function(event) { if (false == !!event) event = window.event; var direction = ((event.wheelDelta) ? event.wheelDelta/120 : event.detail/-3) || false; } 

With the first line, everything is clear - this is a crutch for IE. I will tell about the second line in more detail. In it, I determine in which direction the wheel rotates. All browsers except Firefox pass in the wheelDelta property as equal to 120 or -120, depending on where the wheel is spinning. Mozilla operates with the detail property, assigning it values ​​of -3 or 3, respectively. Yes, exactly, the sign does not match. Therefore, the second line I bring the data of different browsers to +1, if the wheel turns up (away from you) and -1, if the wheel turns down (toward you). Well, I put on a condom in the form of "|| false in case of a nuclear war or some other exotic thing.
')
The program is at least completed. I catch the mouse wheel scrolling event in all browsers and even know which direction the wheel is spinning. We go further.

Now we need to catch this event over a certain block, and to do something with it. This may be, for example, the same scrolling content or volume control of the player. I, as an example, decided to make a kind of colorpicker, in which the values ​​of the red, green or blue components are set by scrolling the wheel over the corresponding block. That is, something in this spirit:

image

I decided to act in the simplest way and maybe even in a slightly kondovo way: I entered the wheel_handle global variable (null or another false-like default value), which at the onmouseover event on a certain block will be assigned a certain function defined in advance. The function will be executed when onmousewheel is triggered and the scroll direction will be transmitted to it as a parameter. The code began to look like this:
 var wheel_handle = null; var mouse_wheel = function(event) { if (false == !!event) event = window.event; var direction = ((event.wheelDelta) ? event.wheelDelta/120 : event.detail/-3) || false; if (direction && !!wheel_handle && typeof wheel_handle == "function") {  wheel_handle(direction); } } var set_handle = function(id, func) { document.getElementById(id).onmouseover = function() {  wheel_handle = func; } document.getElementById(id).onmouseout = function() {  wheel_handle = null; } } window.onload = function() { if (window.addEventListener) window.addEventListener("DOMMouseScroll", mouse_wheel, false); window.onmousewheel = document.onmousewheel = mouse_wheel; } 

In principle, everything should be clear, but just in case. The mouse_wheel function, in the presence of direction and wheel_handle with the type “function”, performs the function assigned to wheel_handle. The function set_handle determines which blocks to perform which function. That is, a little running forward, for my example, the construction

 set_handle("r", set_red); 

will mean that when you hover the mouse over the block with the identifier "r", the wheel_handle variable is assigned the function set_red, which with the direction parameter will be executed in the event of an onmousewheel event.

I make an example:
 <!DOCTYPE html> <html> <head>  <style type="text/css">   #r { position: absolute; left: 10px; top: 10px; width: 100px; height: 100px; font-size: 50px; color: #fff; text-align: center; line-height: 100px; background: #000; }   #g { position: absolute; left: 120px; top: 10px; width: 100px; height: 100px; font-size: 50px; color: #fff; text-align: center; line-height:100px; background: #000; }   #b { position: absolute; left: 230px; top: 10px; width: 100px; height: 100px; font-size: 50px; color: #fff; text-align: center; line-height:100px; background: #000; }   #result { position: absolute; left: 10px; top: 120px; width: 320px; height: 100px; background: #000; }  </style>  <script type="text/javascript">   var wheel_handle = null;   var rgb = {    r: 0,    g: 0,    b: 0,    result: 0   } var mouse_wheel = function(event) { if (false == !!event) event = window.event; var direction = ((event.wheelDelta) ? event.wheelDelta/120 : event.detail/-3) || false; if (direction && !!wheel_handle && typeof wheel_handle == "function") { wheel_handle(direction); } } var set_handle = function(id, func) { document.getElementById(id).onmouseover = function() { wheel_handle = func; }; document.getElementById(id).onmouseout = function() { wheel_handle = null; }; } var set_red = function(direction) { rgb.r += direction; if (rgb.r < 0) rgb.r = 0; if (rgb.r > 255) rgb.r = 255; document.getElementById("r").innerHTML = rgb.r; document.getElementById("r").style.backgroundColor = "rgb(" + rgb.r + ", 0, 0)"; set_result(); } var set_green = function(direction) { rgb.g += direction; if (rgb.g < 0) rgb.g = 0; if (rgb.g > 255) rgb.g = 255; document.getElementById("g").innerHTML = rgb.g; document.getElementById("g").style.backgroundColor = "rgb(0, " + rgb.g + ", 0)"; set_result(); } var set_blue = function(direction) { rgb.b += direction; if (rgb.b < 0) rgb.b = 0; if (rgb.b > 255) rgb.b = 255; document.getElementById("b").innerHTML = rgb.b; document.getElementById("b").style.backgroundColor = "rgb(0, 0, " + rgb.b + ")"; set_result(); } var set_result = function() { document.getElementById("result").style.backgroundColor = "rgb(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ")"; } window.onload = function() { if (window.addEventListener) window.addEventListener("DOMMouseScroll", mouse_wheel, false); window.onmousewheel = document.onmousewheel = mouse_wheel; set_handle("r", set_red); set_handle("g", set_green); set_handle("b", set_blue); } </script> </head> <body style="height: 1000px;"> <div id="r">0</div> <div id="g">0</div> <div id="b">0</div> <div id="result"></div> </body> </html> 

Set_ * type finctions are obvious and, in my opinion, do not need comments. But pay attention to the style of the body tag is necessary. I set 1000 pixels of height so that the page is guaranteed not to fit in the screen and it has formed its own scroll bar. If you run the example in this form, the onmousewheel events on the blocks will work, but the page itself will scroll down. I re-read the problem statement; I put a small dash into the mouse_wheel () function;
 var mouse_wheel = function(event) { if (false == !!event) event = window.event; var direction = ((event.wheelDelta) ? event.wheelDelta/120 : event.detail/-3) || false; if (direction && !!wheel_handle && typeof wheel_handle == "function") { if (event.preventDefault) event.preventDefault(); event.returnValue = false; wheel_handle(direction); } } 

preventDefault () is needed here to cancel an event. And in general, it is needed to cancel the event. In general, I quote a little Google:
If the event action can be canceled, the preventDefault () method of the Event object is used to cancel the event. This means that the action performed in a particular implementation will not be executed when this event occurs. If the preventDefault () method is called at any phase of the event, the event is canceled. The action performed by this default event is not executed. Calling this method for an event that cannot be canceled has no effect on the further execution of the event. After the call, the preventDefault () method will be valid for the duration of the event further propagation. The preventDefault () method can be called at any phase of the event flow.


event.returnValue is for IE, which does not know about preventDefault ().

We canceled the natural reaction to the event - we perform our function. Under Windows in the eighth Firefox, I noted the not always correct triggering of preventDefault (). Although, maybe this is some onmouseenter specifics, because it was noticed that incorrect responses occur when the cursor is on text in a block. If anyone is aware of these cataclysms, enlighten, please - Google did not help here.

But, in general, that's all. The source code for copy-paste completely:
 <!DOCTYPE html> <html> <head> <style type="text/css"> #r { position: absolute; left: 10px; top: 10px; width: 100px; height: 100px; font-size: 50px; color: #fff; text-align: center; line-height: 100px; background: #000; } #g { position: absolute; left: 120px; top: 10px; width: 100px; height: 100px; font-size: 50px; color: #fff; text-align: center; line-height:100px; background: #000; } #b { position: absolute; left: 230px; top: 10px; width: 100px; height: 100px; font-size: 50px; color: #fff; text-align: center; line-height:100px; background: #000; } #result { position: absolute; left: 10px; top: 120px; width: 320px; height: 100px; background: #000; } </style> <script type="text/javascript"> var wheel_handle = null; var rgb = { r: 0, g: 0, b: 0, result: 0 } var mouse_wheel = function(event) { if (false == !!event) event = window.event; var direction = ((event.wheelDelta) ? event.wheelDelta/120 : event.detail/-3) || false; if (direction && !!wheel_handle && typeof wheel_handle == "function") { if (event.preventDefault) event.preventDefault(); event.returnValue = false; wheel_handle(direction); } } var set_handle = function(id, func) { document.getElementById(id).onmouseover = function() { wheel_handle = func; } document.getElementById(id).onmouseout = function() { wheel_handle = null; } } var set_red = function(direction) { rgb.r += direction; if (rgb.r < 0) rgb.r = 0; if (rgb.r > 255) rgb.r = 255; document.getElementById("r").innerHTML = rgb.r; document.getElementById("r").style.backgroundColor = "rgb(" + rgb.r + ", 0, 0)"; set_result(); } var set_green = function(direction) { rgb.g += direction; if (rgb.g < 0) rgb.g = 0; if (rgb.g > 255) rgb.g = 255; document.getElementById("g").innerHTML = rgb.g; document.getElementById("g").style.backgroundColor = "rgb(0, " + rgb.g + ", 0)"; set_result(); } var set_blue = function(direction) { rgb.b += direction; if (rgb.b < 0) rgb.b = 0; if (rgb.b > 255) rgb.b = 255; document.getElementById("b").innerHTML = rgb.b; document.getElementById("b").style.backgroundColor = "rgb(0, 0, " + rgb.b + ")"; set_result(); } var set_result = function() { document.getElementById("result").style.backgroundColor = "rgb(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ")"; } window.onload = function() { if (window.addEventListener) window.addEventListener("DOMMouseScroll", mouse_wheel, false); window.onmousewheel = document.onmousewheel = mouse_wheel; set_handle("r", set_red); set_handle("g", set_green); set_handle("b", set_blue); } </script> </head> <body style="height: 1000px;"> <div id="r">0</div> <div id="g">0</div> <div id="b">0</div> <div id="result"></div> </body> </html> 


Reference to a working example

NB! Link to a working example, supplemented with the advice of distinguished commentators
- fixed binding to "magic constants";
- added the ability to specify the context of the call to handle: the binding function now looks like mousewheel.set_wheel_handle (id, func, context);
- everything relating to onmousewheel is wrapped in the Mousewheel.js library.

And, in fact, what have the onion soup. Well, first . And, secondly, I do not know about you, but here in Moscow the frosts hit. -10, of course, is tolerable, but cold colds are blooming right now. Unpleasant, agree?

I don’t know a better remedy for the prevention of any colds, than a bowl of hot, fragrant onion soup in a Rouen manner, and I cook it like this:


Bon appetit, in general. Of course, preparation takes at least 4 hours, but the result is worth it, believe me. And in general, I see a number of similarities between cooks and programmers, but more on that next time, and probably all the same, in Habrayour.

Do not be ill!

Source: https://habr.com/ru/post/133321/


All Articles