your browser is not capable for the future
the text in the area continues beyond the bottom border — this is indicated by the content fading out to a special texture
Event horizon
In general relativity, an event horizon is a boundary in spacetime beyond which events cannot affect an outside observer. In layman's terms, it is defined as "the point of no return", i.e., the point at which the gravitational pull becomes so great as to make escape impossible. An event horizon is most commonly associated with black holes. Light emitted from beyond the event horizon can never reach the outside observer. Likewise, any object approaching the horizon from the observer's side appears to slow down and never quite pass through the horizon, with its image becoming more and more redshifted as time elapses. The traveling object, however, experiences no strange effects and does, in fact, pass through the horizon in a finite amount of proper time.
More specific types of horizon include the related but distinct absolute and apparent horizons found around a black hole. Still other distinct notions include the Cauchy and Killing horizon; the photon spheres and ergospheres of the Kerr solution; particle and cosmological horizons relevant to cosmology; and isolated and dynamical horizons important in current black hole research.
Event horizon of a black hole
One of the best-known examples of an event horizon derives from general relativity's description of a black hole, a celestial object so massive that no nearby matter or radiation can escape its gravitational field. Often, this is described as the boundary within which the black hole's escape velocity is greater than the speed of light. However, a more accurate description is that within this horizon, all lightlike paths (paths that light could take) and hence all paths in the forward light cones of particles within the horizon, are warped so as to fall farther into the hole. Once a particle is inside the horizon, moving into the hole is as inevitable as moving forward in time, and can actually be thought of as equivalent to doing so, depending on the spacetime coordinate system used.
The surface at the Schwarzschild radius acts as an event horizon in a non-rotating body that fits inside this radius (although a rotating black hole operates slightly differently). The Schwarzschild radius of an object is proportional to its mass. Theoretically, any amount of matter will become a black hole if compressed into a space that fits within its corresponding Schwarzschild radius. For the mass of the Sun this radius is approximately 3 kilometers and for the Earth it is about 9 millimeters. In practice, however, neither the Earth nor the Sun has the necessary mass and therefore the necessary gravitational force, to overcome electron and neutron degeneracy pressure. The minimal mass required for a star to be able to collapse beyond these pressures is the Tolman-Oppenheimer-Volkoff limit, which is approximately three solar masses.
Black hole event horizons are widely misunderstood. Common, although erroneous, is the notion that black holes “vacuum up” material in their neighborhood, where in fact they are no more capable of “seeking out” material to consume than any other gravitational attractor. As with any mass in the universe, matter must come within its gravitational scope for the possibility to exist of capture or consolidation with any other mass. Equally common is the idea that matter can be observed “falling into” a black hole. This is not possible. Astronomers can only detect accretion disks around black holes, where material moves with such speed that friction creates high-energy radiation which can be detected. (Similarly, some matter from these accretion disks is forced out along the axes of spin of the black hole, creating visible jets when these streams interact with matter such as interstellar gas or when they happen to be aimed directly at earth.) Further, relativity dictates that anything approaching an event horizon will, from the point of view of an observer, never actually cross the horizon, but will approach ever more slowly, gaining mass as it does so and, correspondingly, any light it emits will be further and further redshifted.
Cosmic event horizon
In cosmology, the event horizon of the observable universe is the largest comoving distance from which light emitted now can ever reach the observer in the future. This differs from the concept of particle horizon, which represents the largest comoving distance from which light emitted in the past could have reached the observer at a given time. For events beyond that distance, light has not had time to reach our location, even if it were emitted at the time the universe began. How the particle horizon changes with time depends on the nature of the expansion of the universe. If the expansion has certain characteristics, there are parts of the universe that will never be observable, no matter how long the observer waits for light from those regions to arrive. The boundary past which events cannot ever be observed is an event horizon, and it represents the maximum extent of the particle horizon.
Examples of cosmological models without an event horizon are universes dominated by matter or by radiation. An example of a cosmological model with an event horizon is a universe dominated by the cosmological constant (a de Sitter universe).
A calculation of the speeds of the cosmological event and particle horizons was given in a paper on the FLRW cosmological model, approximating the universe as composed of non-interacting constituents, each one being a perfect fluid.
Apparent horizon of an accelerated particle
If a particle is moving at a constant velocity in a non-expanding universe free of gravitational fields, any event that occurs in that universe will eventually be observable by the particle, because the forward light cones from these events intersect the particle's world line. On the other hand, if the particle is accelerating, in some situations light cones from some events never intersect the particle's world line. Under these conditions, an apparent horizon is present in the particle's (accelerating) reference frame, representing a boundary beyond which events are unobservable.
For example, this occurs with a uniformly accelerated particle. A space-time diagram of this situation is shown in the figure to the right. As the particle accelerates, it approaches, but never reaches, the speed of light with respect to its original reference frame. On the space-time diagram, its path is a hyperbola, which asymptotically approaches a 45 degree line (the path of a light ray). An event whose light cone's edge is this asymptote or is farther away than this asymptote can never be observed by the accelerating particle. In the particle's reference frame, there appears to be a boundary behind it from which no signals can escape (an apparent horizon).
While approximations of this type of situation can occur in the real world (in particle accelerators, for example), a true event horizon is never present, as the particle must be accelerated indefinitely (requiring arbitrarily large amounts of energy and an arbitrarily large apparatus).
Interacting with an event horizon
A misconception concerning event horizons, especially black hole event horizons, is that they represent an immutable surface that destroys objects that approach them. In practice, all event horizons appear to be some distance away from any observer, and objects sent towards an event horizon never appear to cross it from the sending observer's point of view (as the horizon-crossing event's light cone never intersects the observer's world line). Attempting to make an object near the horizon remain stationary with respect to an observer requires applying a force whose magnitude increases unbounded (becoming infinite) the closer it gets.
For the case of a horizon perceived by a uniformly accelerating observer in empty space, the horizon seems to remain a fixed distance from the observer no matter how its surroundings move. Varying the observer's acceleration may cause the horizon to appear to move over time, or may prevent an event horizon from existing, depending on the acceleration function chosen. The observer never touches the horizon and never passes a location where it appeared to be.
For the case of a horizon perceived by an occupant of a de Sitter Universe, the horizon always appears to be a fixed distance away for a non-accelerating observer. It is never contacted, even by an accelerating observer.
For the case of the horizon around a black hole, observers stationary with respect to a distant object will all agree on where the horizon is. While this seems to allow an observer lowered towards the hole on a rope (or rod) to contact the horizon, in practice this cannot be done. The proper distance to the horizon is finite, so the length of rope needed would be finite as well, but if the rope were lowered slowly (so that each point on the rope was approximately at rest in Schwarzschild coordinates), the proper acceleration (G-force) experienced by points on the rope closer and closer to the horizon would approach infinity, so the rope would be torn apart. If the rope is lowered quickly (perhaps even in freefall), then indeed the observer at the bottom of the rope can touch and even cross the event horizon. But once this happens it is impossible to pull the bottom of rope back out of the event horizon, since if the rope is pulled taut, the forces along the rope increase without bound as they approach the event horizon and at some point the rope must break. Furthermore, the break must occur not at the event horizon, but at a point where the second observer can observe it.
Observers crossing a black hole event horizon can calculate the moment they have crossed it, but will not actually see or feel anything special happen at that moment. In terms of visual appearance, observers who fall into the hole perceive the black region constituting the horizon as lying at some apparent distance below them, and never experience crossing this visual horizon. Other objects that had entered the horizon along the same radial path but at an earlier time would appear below the observer but still above the visual position of the horizon, and if they had fallen in recently enough the observer could exchange messages with them before either one was destroyed by the gravitational singularity. Increasing tidal forces (and eventual impact with the hole's singularity) are the only locally noticeable effects.
Beyond general relativity
The description of event horizons given by general relativity is thought to be incomplete. When the conditions under which event horizons occur are modeled using a more comprehensive picture of the way the universe works, that includes both relativity and quantum mechanics, event horizons are expected to have properties that are different from those predicted using general relativity alone.
At present, it is expected that the primary impact of quantum effects is for event horizons to possess a temperature and so emit radiation. For black holes, this manifests as Hawking radiation, and the larger question of how the black hole possesses a temperature is part of the topic of black hole thermodynamics. For accelerating particles, this manifests as the Unruh effect, which causes space around the particle to appear to be filled with matter and radiation.
A complete description of event horizons is expected to, at minimum, require a theory of quantum gravity. One such candidate theory is M-theory. Another such candidate theory is loop quantum gravity.
Loop quantum gravity
Loop quantum gravity is a theory that attempts to describe the quantum properties of the universe and gravity. It is also a theory of quantum space and quantum time because, according to general relativity, the geometry of spacetime is a manifestation of gravity. LQG is an attempt to merge and adapt standard quantum mechanics and standard general relativity. The main output of the theory is a physical picture of space where space is granular. The granularity is a direct consequence of the quantization. It has the same nature as the granularity of the photons in the quantum theory of electromagnetism or the discrete levels of the energy of the atoms. Here, it is space itself that is discrete. In other words, there is a minimum distance possible to travel through it.
More precisely, space can be viewed as an extremely fine fabric or network "woven" of finite loops. These networks of loops are called spin networks. The evolution of a spin network over time is called a spin foam. The predicted size of this structure is the Planck length, which is approximately 10−35 meters. According to the theory, there is no meaning to distance at scales smaller than the Planck scale. Therefore, LQG predicts that not just matter, but also space itself has an atomic structure.
Today LQG is a vast area of research, developing in several directions, which involves about 30 research groups worldwide. They all share the basic physical assumptions and the mathematical description of quantum space. The full development of the theory is being pursued in two directions: the more traditional canonical loop quantum gravity, and the newer covariant loop quantum gravity, more commonly called spin foam theory.
Research into the physical consequences of the theory is proceeding in several directions. Among these, the most well-developed is the application of LQG to cosmology, called loop quantum cosmology (LQC). LQC applies LQG ideas to the study of the early universe and the physics of the Big Bang. Its most spectacular consequence is that the evolution of the universe can be continued beyond the Big Bang. The Big Bang appears thus to be replaced by a sort of cosmic Big Bounce.
In 1986, Abhay Ashtekar reformulated Einstein's general relativity in a language closer to that of the rest of fundamental physics. Shortly after, Ted Jacobson and Lee Smolin realized that the formal equation of quantum gravity, called the Wheeler–DeWitt equation, admitted solutions labelled by loops, when rewritten in the new Ashtekar variables, and Carlo Rovelli and Lee Smolin defined a nonperturbative and background-independent quantum theory of gravity in terms of these loop solutions. Jorge Pullin and Jerzy Lewandowski understood that the intersections of the loops are essential for the consistency of the theory, and the theory should be formulated in terms of intersecting loops, or graphs.
In 1994, Rovelli and Smolin showed that the quantum operators of the theory associated to area and volume have a discrete spectrum. That is, geometry is quantized. This result defines an explicit basis of states of quantum geometry, which turned out to be labelled by Roger Penrose's spin networks, which are graphs labelled by spins.
The canonical version of the dynamics was put on firm ground by Thomas Thiemann, who defined an anomaly-free Hamiltonian operator, showing the existence of a mathematically consistent background-independent theory. The covariant or spinfoam version of the dynamics developed during several decades, and crystallized in 2008, from the joint work of research groups in France, Canada, UK, Poland, and Germany, lead to the definition of a family of transition amplitudes, which in the classical limit can be shown to be related to a family of truncations of general relativity. The finiteness of these amplitudes was proven in 2011. It requires the existence of a positive cosmological constant, and this is consistent with observed acceleration in the expansion of the Universe.
almost at the top
is above the top
is visible
the bottom border
Reese's Pieces are a product extension of the Reese's Peanut Butter Cups line; this new product was designed to capitalize on the success of the chocolate-covered peanut butter cups.
In 2012, Vanparys extended its range of confections to include a gourmet range of chocolate-coated nuts, fruits and coffee beans – as well as a variety of seasonal confectioneries such as praliné eggs and fondant chicks for Easter.
Presently the company is located in Evere, Brussels, and exports to many countries including the Netherlands, France, Luxembourg, UK, Germany, Poland, China, Turkey, Tunisia, Japan and Portugal.
Each season, Vanparys introduces a range of new colours to its palette
Prince Polo was introduced in 1955, during the early years of the Polish People's Republic, by Olza S.A. in Cieszyn. It is a chocolate-covered wafer, with four layers of wafer joined by three layers of chocolate-flavored filling; it was easily identifiable by its metallic gold-colored wrapper.
Chocolate 'geld' is also given to children as part of the St. Nicholas holiday in Belgium, Germany and the Netherlands (geld, spelled with a d, being both the Dutch and German word for money). Today most of the chocolate Hanukkah gelt sold in the United States is imported, including from Dutch firms Steenland Chocolate and the Israeli firms Elite and Carmit. But gourmet versions of chocolate gelt have been produced in the United States by companies like California-based Sweet Earth Organic Chocolates and Vermont-based Lake Champlain Chocolates. In England, Divine Chocolates makes gourmet gelt. Verucca Chocolates in Chicago makes very elegant beautifully designed gelt designed to look like Maccabean coins.
Big Hunk Bars are very chewy, and are known for its bright, high energy and colorful advertisements such as the line "PUT BIG PROFITS IN YOUR POCKET WITH BIG HUNK".
In 1969, Schutter-Johnson was merged into the Ward Candy Company of New York City, makers of other candies, including Chunky, Oh Henry! and Raisinets. Between the mid- and late-1970s, a chocolate-flavored version called Bit-O-Chocolate was made, but this product was later dropped. Other spin-offs included Bit o' Licorice and Bit-O-Peanut Butter.
Bit-O-Honey and most of Ward's other brands were acquired by the Nestlé Company in 1984. In May of 2013, Nestlé sold the Bit-O-Honey brand to the Pearson's Candy Company of Saint Paul, Minnesota.
Bit-O-Honey is similar in style and packaging (single pieces) to Mary Jane made by Necco. Ingredients as of 2013: Corn syrup, sugar, non-fat milk, hydrogenated coconut oil, almonds, honey, salt, egg whites, canola and/or safflower and/or palm oil, modified soy protein, natural flavor, TBHQ and citric acid.
Mounds' original slogan, "Indescribably Delicious",.was created when Mounds ran a contest to come up with the best two words to sell a candy. Leon Weiss, the person who came up with the slogan, won $10, while Mounds went on to use the slogan in advertising and on the wrappers, still continuing today.
Mounds uses a packaging and logo design similar to its sister product, with Almond Joy's blue replaced by red, and the two candies are often advertised together. The candy's famous 1970s ad campaign used a jingle, "Sometimes you feel like a nut, sometimes you don't / Almond Joy's got nuts / Mounds don't", written by Leon Carr.
A limited edition Mounds Island Orange candy bar was introduced in 2006 with orange colored and flavored coconut.
A similar coconut-filled chocolate bar by the name of Bounty is manufactured by Mars, Incorporated and sold in markets other than the United States. The bars come in light or dark chocolate and are recognized by their blue (light chocolate) or red (dark chocolate) wrappers. Neither bar contains almonds.
It is a truffle type bar with almond bits covered in chocolate and comes wrapped in a silver foil-like wrapper. It is comparable to a 3 Musketeers except it has a much higher fat content compared to 3 Musketeers with a much thinner chocolate shell and more moussy nougat. U-no bars used to come in two flavors: Original and mint. Annabelle Candy Company has since discontinued the mint flavor.
It was first produced by the Cardinet Candy Company, which was later acquired by the Annabelle Candy Company.
However, in 2004 the Necco company brought the Squirrel Nut candy brand back to Massachusetts.
In 2003, the former factory building in Cambridge was converted to affordable public housing apartments. A public park and community gardening space, named Squirrel Brand Park, is now located next to the former factory.
Cadbury is best known for its confectionery products including the Dairy Milk chocolate, the Creme Egg, and the Roses selection box.
Cadbury was established in Birmingham, England in 1824, by John Cadbury who sold tea, coffee and drinking chocolate. Cadbury developed the business with his brother Benjamin, followed by his sons Richard and George. George developed the Bournville estate, a model village designed to give the company's workers improved living conditions. Dairy Milk chocolate, introduced in 1905, used a higher proportion of milk within the recipe compared with rival products. By 1914, the chocolate was the company's best-selling product.
Cadbury merged with J. S. Fry & Sons in 1919, and Schweppes in 1969. Cadbury was a constant constituent of the FTSE 100 from the index's 1984 inception until the company was bought by Kraft Foods in 2010.
Many varieties of Kit Kat have existed, either permanently or as limited editions, such as those sold to commemorate festivals such as St. Valentine's Day. In Japan, Nestlé has introduced over 200 different flavours since 2000, including ginger ale, soy sauce, creme brulee, green tea, and banana. The flavours are designed to appeal to younger buyers, and are often bought as good-luck gifts as the brand name echoes the Japanese phrase "Kitto Katsu", roughly translating as "surely win."
The Kit Kat Orange was the first flavour variant to be introduced in the United Kingdom, in 1996 and 1998 in Ireland. It was followed in 1997 by the Kit Kat Dark and Kit Kat Mint. All three were available as permanent editions of the two-finger multipack in the United Kingdom, along with the Kit Kat Original, the Kit Kat White, and from 2012 the Kit Kat Cookies & Cream.
The current Maltesers' slogan is "The lighter way to enjoy chocolate" - earlier slogans have included "The Dri Drink", "The chocolates with the less fattening centre", "No ordinary chocolate" and "Nothing pleases like Maltesers". The Australian version also contains the line: "Made in Australia... ...exported to the world." In the 1930s, advertisements claimed that the Maltesers honeycomb centre is seven times less fattening than ordinary chocolate centres; this led marketers to claim it was beneficial for weight loss.
In 2011, the product gained Fairtrade accreditation in the UK and Ireland by sourcing all their cocoa and sugar under Fairtrade Terms.
The European version of the bar has no caramel topping, and consists of a nougat center that is considerably lighter than that of the Mars bar. Because of this low density (0.88 g/cm3), it floats when placed in milk. This rare attribute was used for an advertising campaign in Germany, France, Russia, Belgium, Ireland, Poland, the Netherlands and the United Kingdom.
Originally available within Europe only in chocolate flavor, the center changed to vanilla flavor at around 1993, although the chocolate flavor still remains available in Australia. The bar is also available in banana, mango and strawberry flavors. In the UK, Mars introduced the Flyte bar which is identical to the old-style chocolate flavored Milky Way but only comes in twin packs. Also available in Europe are Milky Way Crispy Rolls, chocolate covered wafer rolls with a milk-cream filling.
The Rolo product was developed in the UK by Mackintosh's, (later Rowntree-Mackintosh), simply a combination of Mackintosh's Toffee and a chocolate coating - the acquisition of Caley's of Norwich had also led to the Quality Street line. Rolo was first sold in 1937.
The product was first produced in the United Kingdom in 1967, and introduced in the United States in 1979. Twix was called Raider in Austria, Belgium, Denmark, Finland, France, Germany, Greece, Israel, Italy, Luxembourg, the Netherlands, Norway, Poland, Portugal, Spain, Sweden, Switzerland, and Turkey for many years before its name was changed in 1991 (2000 in Denmark, Finland, Norway, Sweden and Turkey) to match the international brand name.
According to the Candy Wrapper Museum, the first Abba Zaba bars were manufactured beginning in 1922 by Colby and McDermott. Before Annabelle Candy Co. started manufacturing Abba-Zaba, the packaging featured imagery which some now consider to be racially biased. Annabelle Candy Co. will only say that the wrapper has been the same for as long as they have manufactured the candy.
The bar was later manufactured by the Cardinet Candy Co. along with U-No Bar. Annabelle Candy Purchased the Cardinet Candy Co. in 1978. Annabelle now manufactures both candy bars in addition to others.
Abba-Zaba bars are kosher pareve.
Mary Jane is dairy-free, egg-free, and gluten-free and is similar in style, taste and packaging to the Schutter-Johnson Company's (now Pearson's Candy Company) Bit-O-Honey, which appeared in 1924.
/** * Stores a setter function and reuses it to perform smooth * animation on demand * * @param {Function} setter updating the value to be animated */ var Animator = function(setter) { this._setter = setter; this._current = 0; this._target = null; this._delta = null; this._animTimeout = null; } /** * Changes the value instantly (the most reasonable strategy * selected instead in case when animation is running) * * @param {Number} val to set */ Animator.prototype.jump = function(val) { if (this._animTimeout) { var c = this._current, t = this._target, // old target v = val; // new target if ((t > c && v > t) || (t < c && v < t)) { // value beyond the target, speeding up this._delta *= (v-c)/(t-c); this._target = val; } else if ((t > c && v < c) || (t < c && v > c)) { // value in the opposite direction, jumping this._clearTimeout(); this._applyValue(val); } else { // value prior to the target, same direction // simply updating the target this._target = val; } } else { this._applyValue(val); } } /** * Changes the value smoothly * * @param {Number} val to be finally reached */ Animator.prototype.slide = function(val) { this._target = val; if (this._target != this._current) { this._delta = (this._target-this._current)* cfg.animationDelay/cfg.animationTime; } // otherwise will stop upon the next tick if (!this._animTimeout) { this._tick(); } } /** * Performs a single animation step */ Animator.prototype._tick = function() { if (Math.abs(this._target - this._current) < Math.abs(this._delta)) { if (this._animTimeout) { this._clearTimeout(); } this._applyValue(this._target); } else { var me = this; this._animTimeout = setTimeout( function(){me._tick();}, cfg.animationDelay ); this._applyValue(this._current+this._delta); } } /** * Applies current animation frame * * @param {Number} value to apply */ Animator.prototype._applyValue = function(value) { this._current = value; this._setter(value); } /** * Clears animation timeout */ Animator.prototype._clearTimeout = function() { clearTimeout(this._animTimeout); this._animTimeout = null; } // stores the images along with the stretched canvas var imgCache = {}; /** * Represents a single cached stretchable image * * Loads an image, creates a stretched canvas */ var CachedImg = function(url) { if (typeof imgCache[url] != 'undefined') { return imgCache[url]; } else { imgCache[url] = this; this._url = url; this._touchTimeout = null; this._ready = new wl.Whenable; this.whenReady = this._ready.getSubscriber(); this._sides = {}; // stretched canvases this._data = {}; this._SVGImage = null; this._SVGImageId = null; this._download(); } } /** * Loads the image */ CachedImg.prototype._download = function() { if (!this._url) { this._init(null); this._ready.emit(); } else { this._img = elemSample.img.cloneNode(false); this._img.src = this._url; this._img.style.display = 'none'; var me = this; this._img.addEventListener('load', function() { me._img.parentNode.removeChild(me._img); me._init(me._img); me._ready.emit(); }, false); this._img.addEventListener('error', function() { me._img.parentNode.removeChild(me._img); me._init(null); me._ready.emit(); }, false); document.body.appendChild(this._img); } } /** * Creates the cached copy of rotated canvas (if needed), and * returns it afterwards * * @param {String} dir direction */ CachedImg.prototype.getSide = function(dir) { if (typeof this._sides[dir] == 'undefined') { this._sides[dir] = this._rotate(this._sides.north, dir); } return this._sides[dir]; } /** * Creates (if not done yet) an SVG image element containing the * stretched image and stored in the common element, * returns its id * * @param {String} id of an SVG element with the stretched image */ var SVGImageCounter = 0; CachedImg.prototype.getSVGImageId = function() { if (!this._SVGImage) { this._SVGImageId ='SVG-Image-'+(SVGImageCounter++)+'-'+UQ; var canvas = this._sides.north; var url = util.getCanvasDataURL(canvas); var defs = util.getCommonSVGDefs(); this._SVGImage = util.genSVGElement('image', defs, { id : this._SVGImageId, x : '0', y : '0', width : util.px(canvas.width), height : util.px(canvas.height), preserveAspectRatio : 'none' }); this._SVGImage.setAttributeNS( util._xlinkNS, 'xlink:href', url[0] ); } return this._SVGImageId; } /** * Updates image geometry without changing it. Needed for IE, * otherwise it will not redraw */ CachedImg.prototype.touchSVGImage = function() { if (IS_IE && this._SVGImage) { if (this._touchTimeout) { clearTimeout(this._touchTimeout); } var me = this; this._touchTimeout = setTimeout( function() { me._touch(); }, 10 ); } } CachedImg.prototype._touch = function() { this._SVGImage.setAttribute( 'height', util.px(this._data.stretchedSize) ); } /** * @returns {Object} additional data */ CachedImg.prototype.getData = function() { return this._data; } /** * After the image is loaded (or failed to load), ininitializes * the CachedImg object with its stretched canvas images, and with * some additional data later used for animation * * @param {Element} image to initalize from, null for load failure */ CachedImg.prototype._init = function(image) { var original = this._genImageCanvas(image); var stretched = this._stretch(original); this._sides.north = stretched.canvas; this._data = this._genData(stretched.canvas); this._data.points = stretched.points; this._data.origSize = original.height; } /** * Generates a canvas containing the data from the provided image, * or the default data if image failed to load * * @param {Element} image to initalize from, null for load failure * * @returns {Element} canvas */ CachedImg.prototype._genImageCanvas = function(image) { var result; if (image) { result = util.img2canvas(image); } else { result = util.getDefaultCanvas(); } return result; } /** * Stretches the given canvas data and returns the new canvas with * the stretched content. The image is stretched in a special way, * so that horizontal pixels density is unchanged, but the * vertical density is decreased from top to bottom. Pixels on the * top edge have the same density as the original image, while the * pixels on the bottom edge are 4 times vertically stretched. * * The density function * * ro(x) = 45/68*x*x - 24/17*x + 1 * * results from the following conditions: * * 1) ro(0) = 1 (destiny at the top edge equals the orig. image) * 2) ro(1) = 1/4 (density at the bottom is 4 times less) * 3) ro'(1) = ro2'(0), where: * ro2(x) = 1/4 * ro(x/4), which is a density of the same * image, linearly stretched four times. The last condition * means that the speed of density change for the two images * attached one to another is continuous * * @param {Element} canvas containing the original image * * @returns {Object} stretched canvas and density points */ CachedImg.prototype._stretch = function(canvas) { var w = canvas.width; var h = canvas.height; // if webkit throws an error for a local image, // restart Chrome with --allow-file-access-from-files // (otherwise load an image from the same origin) var data1 = canvas.getContext('2d').getImageData(0, 0, w, h); var h2 = h * 68 / 35; var h2floor = Math.floor(h2); var stretchedCanvas = util.genCanvas(w, h2floor); var ctx2 = stretchedCanvas.getContext('2d'); var data2 = ctx2.createImageData(w, h2floor); var D1 = data1.data; var D2 = data2.data; var ro; // current density value var y2; // y, stretched image var y1; // y, original image (calculated, float) var y1_floor; // y, original image (floored) var y2_norm; // y2 / h2 (normalized, 0 <= y2_norm <= 1) var y2_norm_2; // y2_norm squared var y1_norm; // calculated normalized y of the orig img var rate0; // ratios of the current pixel, var rate1; // and the one on the next row var row = w*4; // imageData row (4 channels) var idx1; // current pixel start idx (original image) var idx2; // current pixel start idx (stretched image) var col; // runs through columns (pixels) var ch; // runs through color channels // saves the current coordinate of the stretched image // indexed by original coordinate (so that it is possible to // restore current position of the stretched image by the // coordinate of the original image) var points = []; var _15_68 = 15/68; var _12_17 = 12/17; var _45_68 = 45/68; var _24_17 = 24/17; // generating image for (y2 = 0; y2 < h2floor; y2++) { y2_norm = y2/h2; y2_norm_2 = y2_norm * y2_norm; // destiny at the point of y2 ro = _45_68 * y2_norm_2 - _24_17 * y2_norm + 1; // normalized coordinate of the original image // calculated as antiderivative of density function y1_norm = _15_68 * y2_norm_2 * y2_norm - _12_17 * y2_norm_2 + y2_norm; // current y-coordinate on the original image y1 = y1_norm * h2; y1_floor = Math.floor(y1); points[y1_floor] = y2; rate0 = Math.min(ro, y1_floor + 1 - y1); rate1 = ro - rate0; idx1 = row*y1_floor; idx2 = row*y2; for (col = 0; col < w; col++) { for (ch = 0; ch < 4; ch++) { D2[idx2+ch] = Math.round(( rate0 * D1[idx1+ch] + rate1 * (D1[idx1+ch+row]||0) ) / ro); } idx1 += 4; idx2 += 4; } } ctx2.putImageData(data2, 0, 0); return { canvas: stretchedCanvas, points: points }; } /** * Generates the canvas rotated in the given direction * * @param {Element} north original canvas element * @param {String} dir direction to rotate the canvas * * @returns {Element} rotated canvas */ CachedImg.prototype._rotate = function(north, dir) { var w = north.width; var h = north.height; var rotated; if (util.isVertical[dir]) { rotated = util.genCanvas(w,h); } else { rotated = util.genCanvas(h,w); } var ctx = rotated.getContext('2d'); switch (dir) { case 'east': ctx.rotate(Math.PI/2); ctx.drawImage(north, 0, -h); break; case 'south': ctx.rotate(Math.PI); ctx.drawImage(north, -w, -h); break; case 'west': ctx.rotate(-Math.PI/2); ctx.drawImage(north, -w, 0); break; } return rotated; } /** * Calculates additional data for the given stretched canvas * element later reused for animation * * @param {Element} canvas to generate data for * * @returns {Object} data */ CachedImg.prototype._genData = function(canvas) { var w = canvas.width; var h = canvas.height; // size of the side layer var maxIntensity = 0; var curSize = h; for (var i = 1; i < cfg.blocksNumber; i++) { curSize /= 4; maxIntensity += Math.floor(curSize); } // how many virtual elements do we need to reach 1 px var virtualNum = 1 + Math.ceil(Math.log(1/h) / Math.log(1/4)); // total height of all virtual elements altogether var virtualSize = 0; curSize = h; for (i = 1; i < virtualNum; i++) { curSize /= 4; virtualSize += Math.floor(curSize); } return { // size of the stretched image stretchedSize : h, // texture size along the side sideSize : w, // maximal size of the indicator layer maxIntensity : maxIntensity, // values used during calculations virtualPow : 1-Math.pow(1/4, virtualNum-1), virtualSize3 : virtualSize*3 }; }; /** * Represents an element upgraded with the resize event detector * * @param {Element} elem to upgarde * @param {Boolean} isBody true if element is body * @param {Function} listener to be issued on resize */ var Resizer = function(elem, isBody, listener) { this._elem = elem; this._isBody = isBody; this._listener = listener; if (this._isBody) { window.addEventListener('resize', this._listener, false); // initially updating geometry if (document.readyState == "complete") { this._listener(); } else { window.addEventListener("load", this._listener, false); } } else { this._detector = elemSample.object.cloneNode(false); util.setStyle(this._detector, { display : 'block', position : 'absolute', top : '0px', left : '0px', height : '100%', width : '100%', overflow : 'hidden', pointerEvents : 'none', zIndex : -2048 // specially for IE }); var me = this; this._detector.onload = function() { this.contentDocument.defaultView.addEventListener( 'resize', me._listener, false ); // initially updating geometry me._listener(); } this._detector.type = 'text/html'; if (IS_IE) { this._elem.appendChild(this._detector); this._detector.data = 'about:blank'; } else { this._detector.data = 'about:blank'; this._elem.appendChild(this._detector); } } }; /** * Removes the resize detector from the element */ Resizer.prototype.destroy = function() { if (this._isBody) { window.removeEventListener( 'resize', this._listener, false ); } else { this._elem.removeChild(this._detector); } } /** * Represents a scrollable element shipped with a scrolling * indicator on each of four sides * * @param {Element} elem to create scrollable indicators for */ var Intence = function(elem) { this._destroyed = false; this._elem = elem; this._isBody = (this._elem.nodeName.toLowerCase() == 'body'); this._cmp = {}; // elements created upon scrollbar removal this._sideReady = {}; // info about which sides are initialized this._images = {}; // CachedImg instances for each side this._indicators = {}; // Indicator instances this._totals = {}; // total dimensions for each direction this._sizes = {}; this._addendum = {}; // added to the scroll to prevent jump this._lastOrigCoord = {}; this._createElemStructure(); var rect = this._cmp.scroller.getBoundingClientRect(); var scrollWidth = this._cmp.scroller.scrollWidth; var scrollHeight = this._cmp.scroller.scrollHeight; var i, dir; for (i = 0; i < util.dir.length; i++) { dir = util.dir[i]; this._indicators[dir] = null; this._sideReady[dir] = false; this._addendum[dir] = 0; this._lastOrigCoord[dir] = 0; this._totals[dir] = util.isVertical[dir] ? scrollHeight : scrollWidth; this._sizes[dir] = util.isVertical[dir] ? rect.height : rect.width; } this._loadImages(); } /** * Returns element */ Intence.prototype.getElem = function() { return this._elem; } /** * Upgrades the element with a set of additional elements one * inside another so that the scrollbars are properly hidden, but * the container geometry is preserved * * The resulting structure consists of the following elements: * * elem - initial scrollable element, its original content is * │ taken over, and moves into the container (see below) * │ * └─ wrapper - fits into the elem, has position: relative, so * │ that hosted elements with absolutie position can * │ also fit into the element * │ * ├─ resizer - html object, detects elem resize * │ * └─ contextor - initiates a new stacking context, so that * │ internal z-indices do not mess with the * │ external content * │ * ├─ scroller - the new scrollable element with * │ │ scrollbars (outside of the bounds and * │ │ thus not visible), has z-index: 0 and * │ │ absolute position, which initializes * │ │ another stacking context for the * │ │ hosted content * │ │ * │ └─ pusher - has explicit dimensions updated by * │ │ the resizer event handler, pushes * │ │ the scrollabrs of the scroller out * │ │ of the bounds, has float:left to set * │ │ up a new block formatting context * │ │ (otherwise contained floats would * │ │ affect scroller's geometry) * │ │ * │ └─ container - hosts original content, takes * │ │ over the external margins * │ │ if root elem is body * │ ├─ ... * │ ├─ ... - original content taken over * │ ├─ ... from the root elem * │ : * │ * │ * ├─ west side - indicator sides, ordered to put * ├─ east side north and south on top (z-index * ├─ south side is not used since it messes-up * └─ north side in IE9) */ Intence.prototype._createElemStructure = function() { this._createElements(); this._createResizer(); this._createSides(); } /** * Creates a set of elements */ Intence.prototype._createElements = function() { this._cmp.wrapper = elemSample.div.cloneNode(false); this._cmp.contextor = elemSample.div.cloneNode(false); this._cmp.scroller = elemSample.div.cloneNode(false); this._cmp.pusher = elemSample.div.cloneNode(false); this._cmp.container = elemSample.div.cloneNode(false); var style = { elem : { overflow : 'hidden', padding : '0px' }, wrapper : { position : 'relative', overflow : 'hidden', width : '100%', height : '100%' }, contextor : { position : 'absolute', overflow : 'hidden', width : '100%', height : '100%' }, scroller : { position : 'absolute', overflow : 'scroll', zIndex : 0 }, pusher : { 'float' : 'left' }, container : {} }; this._origStyle = {overflow : this._elem.style.overflow}; if (this._isBody) { var margins = [ 'margin', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft' ]; var cs = window.getComputedStyle(this._elem, null); var i, m; for (i = 0; i < margins.length; i++) { m = margins[i]; style.container[m] = cs[m]; this._origStyle[m] = this._elem.style[m]; } style.elem.margin = 0; } util.setStyle(this._elem, style.elem); util.setStyle(this._cmp.wrapper, style.wrapper); util.setStyle(this._cmp.contextor, style.contextor); util.setStyle(this._cmp.scroller, style.scroller); util.setStyle(this._cmp.pusher, style.pusher); util.setStyle(this._cmp.container, style.container); impl.stackingContext(this._cmp.contextor); var id = this._elem.getAttribute('id'); if (id) { this._cmp.scroller.setAttribute('id', id+'-scroller'); } util.attachChildren( this._cmp.container, util.detachChildren(this._elem) ); this._cmp.pusher.appendChild(this._cmp.container); this._cmp.scroller.appendChild(this._cmp.pusher); this._cmp.contextor.appendChild(this._cmp.scroller); this._cmp.wrapper.appendChild(this._cmp.contextor); this._elem.appendChild(this._cmp.wrapper); } /** * Creates the resizer and subscribes to resize event */ Intence.prototype._createResizer = function() { var me = this; var listener = function() { me._setGeometry(); me._indicate(); } this._resizer = new Resizer(this._cmp.wrapper, this._isBody, listener); } /** * Creates sides to later host the indicators. Sides created in an * order so that north and south are on top. Z-index is not used, * since then sides would mess-up with external content in IE9 * (where stacking context is not appled to contextor) */ Intence.prototype._createSides = function() { this._sides = {}; var order = ['west','east','south','north']; var dir; for (var i = 0; i < order.length; i++) { dir = order[i]; this._sides[dir] = createSideElement(dir); this._cmp.contextor.appendChild(this._sides[dir]); } } /** * Removes additional elements created by _createElemStructure * thus restoring the element into its original state */ Intence.prototype._restoreElemStructure = function() { this._resizer.destroy(); var children = util.detachChildren(this._cmp.container); util.detachChildren(this._elem); for (var prop in this._origStyle) { if (this._origStyle.hasOwnProperty(prop)) { this._elem.style[prop] = this._origStyle[prop]; } } util.attachChildren(this._elem, children); } /** * Updates the subcomponents geometry according to the element * dimensions */ Intence.prototype._setGeometry = function() { var geom = this._cmp.wrapper.getBoundingClientRect(); util.setStyle(this._cmp.pusher, { width : util.px(Math.ceil(geom.width)), height : util.px(Math.ceil(geom.height)) }); } /** * Initiates loading of images corresponding to each side */ Intence.prototype._loadImages = function() { var me = this; var sideInitialized = {}; var defaultUrl = this._elem.getAttribute('scrollimg')||''; var img, dir, url; for (var i = 0; i < util.dir.length; i++) { dir = util.dir[i]; url = this._elem.getAttribute( 'scrollimg'+dir ); img = new CachedImg(url||defaultUrl); sideInitialized[dir] = new wl.Whenable; img.whenReady( (function(dir, img){ return function() { if (!me._destroyed) { me._indicators[dir] = new Indicator( dir, me._cmp.contextor, me._sides[dir], img ); me._sideReady[dir] = true; sideInitialized[dir].emit(); } } })(dir, img) ); this._images[dir] = img; } wl.whenAll( sideInitialized.north.getSubscriber(), sideInitialized.east.getSubscriber(), sideInitialized.south.getSubscriber(), sideInitialized.west.getSubscriber() )(function(){ me._indicate(true); }); this._cmp.scroller.addEventListener( 'scroll', function(){me._indicate();}, false ); } /** * Updates the scrolling indicators on each side according to the * current scroll state of the element * * @param {Boolean} init true to perform initial indicate */ Intence.prototype._indicate = function(init) { var geom = this._cmp.wrapper.getBoundingClientRect(); var scrollInfo = this._getScrollInfo(); var beyond = this._getBeyond(geom, scrollInfo); var infinite = this._getInfinite(); for (var i = 0; i < util.dir.length; i++) { var dir = util.dir[i]; if (this._sideReady[dir]) { var indicator = this._indicators[dir]; var data = this._images[dir].getData(); var sizesChanged = this._haveSizesChanged(dir, geom); var totalsChanged = this._haveTotalsChanged(dir, scrollInfo); var origCoord = this._getOrigCoord( dir, beyond, data.origSize, totalsChanged || sizesChanged ); var areaSize = util.isVertical[dir] ? geom.height : geom.width; var intensity = this._getIntensity( beyond[dir], infinite[dir], data.maxIntensity, areaSize ); var sideOffset = beyond[util.isVertical[dir] ? 'west':'north']; if (dir == 'north' || dir == 'east') { sideOffset = -sideOffset; } indicator.update( geom.width, geom.height, // area geometry data.points[origCoord], // scrolling amount sideOffset, // side offset intensity, totalsChanged, init // intensity ); } } } /** * @returns {Object} the area scrolling information */ Intence.prototype._getScrollInfo = function() { var scroller = this._cmp.scroller; return { width : scroller.scrollWidth, height : scroller.scrollHeight, top : scroller.scrollTop, left : scroller.scrollLeft }; } /** * For the scrollable area returns the amount of pixels scrollable * beyond each side * * For Opera and zoomed page the distances may be non-integer and * it might not be possible to scroll to the end, so the method * rounds-up the values * * @param {Object} geom geometry returned by getBoundingClientRect * @param {Object} scroll area scroll information * * @returns {Object} */ Intence.prototype._getBeyond = function(geom, scroll) { return { north : this._fixCoord(scroll.top), south : this._fixCoord( scroll.height - scroll.top - geom.height ), west : this._fixCoord(scroll.left), east : this._fixCoord( scroll.width - scroll.left - geom.width ) }; } /** * Fixes the geometry coordinate / scrolling amount which might be * reported as negative or non-integer on some browsers / * zoom-levels * * @param {Number} val * * @returns {Number} fixed coordinate (integer >=0) */ Intence.prototype._fixCoord = function(val) { return Math.max(0, Math.floor(val)); } /** * Returns the coordinate of the original (unstretched) texture * which is synced with the scrolling amount * * @param {String} dir direction * @param {Object} beyond set of scrolling amounts * @param {Number} size (height) of the original texture * @param {Boolean} keep true to keep the orig coord and update * the offset instead * * @returns {Number} original coordinate */ Intence.prototype._getOrigCoord = function( dir, beyond, size, keep ) { var origPoint = beyond[dir]; var result = this._mod(origPoint, size); if (keep) { var diff = result - this._lastOrigCoord[dir]; this._addendum[dir] -= diff; this._addendum[dir] = this._addendum[dir] % size; } this._lastOrigCoord[dir] = result; result += this._addendum[dir]; result = this._mod(result, size); return result; } /** * Returns the information about which sides are set as being * infinitely scrollable with scrollInfinite.. attributes * * @returns {Object} */ Intence.prototype._getInfinite = function() { var result = {}, dir, i; for (i = 0; i < util.dir.length; i++) { dir = util.dir[i]; result[dir] = this._elem.getAttribute( 'scrollinfinite'+dir ) !== null; } return result; } /** * Checks if total size of the area changed in the corresponding * dimension. This might happen either due to resize or due to * dynamically changed geometry - in both cases the intensity mask * is updated, but not the blocks coordinates * * @param {String} dir direction * @param {Object} geom geometry returned by getBoundingClientRect * * @returns {Boolean} true if sizes changed, false otherwise */ Intence.prototype._haveSizesChanged = function(dir, geom) { var changed = false; var newSize = util.isVertical[dir] ? geom.height : geom.width; if (this._sizes[dir] != newSize) { changed = true; this._sizes[dir] = newSize; } return changed; } /** * Checks if total size of the scrollable distance changed. This * might happen either due to resize or due to dynamically changed * content - in both cases the intensity mask is updated, but not * the blocks coordinates * * @param {String} dir direction * @param {Object} scroll data of the scroller * * @returns {Boolean} true if total dimensions changed */ Intence.prototype._haveTotalsChanged = function(dir, scroll) { var changed = false; var el = this._cmp.scroller; var newTotal = util.isVertical[dir] ? scroll.height : scroll.width; if (this._totals[dir] != newTotal) { changed = true; this._totals[dir] = newTotal; } return changed; } /** * Returns the division remainder (0 to value-1) * * @param {Number} value * @param {Number} module */ Intence.prototype._mod = function(value, module) { value = value % module; value += module; value = value % module; if (value == module) { value = 0; } return value; } /** * Returns the size of the blocks container which depends on the * scroll amount beyond the border * * @param {Number} beyond number of px beyond the border * @param {Boolean} infinite true if side is set as infinite * @param {Number} maxSize of the container * @param {Number} areaSize visible area size * * @returns {Number} current size of the container */ Intence.prototype._getIntensity = function( beyond, infinite, maxSize, areaSize ) { var intensity = infinite ? 1 : 1 - 1 / (beyond*cfg.indicatorGain + 1); var max = Math.min(maxSize, cfg.indicatorMaxArea * areaSize); var pad = 1; var size = pad + Math.ceil(intensity * (max-pad)) return size; } /** * Removes the additional indicator elements, thus restores the * element in its original state */ Intence.prototype.destroy = function() { this._restoreElemStructure(); this._destroyed = true; }
intence does not provide any controls for changing the scrolling position, and this was done intentionally. From now the issues of scrolling indication and scrolling control are separated: intence designates what is scrollable, and is supposed to work along with a navigation widget, like the menu on the right side. It can be a pager, or an area with small previews, a progress bar, or something totally new and different. For instance, have a look at some examples of the navigation components created with a viewport.js library. Just like as intence better than the scrollbar designates the scrollable area, such components can be designed for the needs of a particular application and solve the navigation issue in a more efficient manner.
intence is shipped as an open-source javascript library [Github] — so you can easily install it on your site or a web-application. It works on recent versions of major browsers (on others it will simply leave the scrollbar untouched):
Download and unpack the library: intence-1.1.4.tar.gz (10KB), or install it using Bower:
$ bower install intence
Load intence.js into your project (that is an UMD module):
<script src="intence.js"></script>
Create a scrollable element with the content in a usual way so that it is equipped with a scrollbar by a browser:
<div id=myElem> Big text goes here... </div>
#myElem { width : 200px; height : 400px; overflow: auto; }
Add the intence class to the element, and specify an image to be used for the indicator as a value of the scrollImg attribute:
<div id=myElem class=intence scrollImg=texture.png> Big text goes here... </div>
That's it! Now the scrollbar is replaced with the intence indicator composed out of the texture.png. You can also apply the intence class to the <body> element and get the whole page indicated.
When selecting a texture for indication, have in mind that it will be strongly squeezed vertically:
The shapes on the texture can be highly detailed horizontally, but should have significant size in vertical dimension
The texture image is rotated to have its top oriented towards a side of a scrollable area:
The texture rolls within an indicator at a different speed: the closer it is to the area side, the slower it moves. But additionally it depends on the height of the texture, which means you can affect the roll speed by selecting a higher or a lower image:
slowly scroll the areas by dragging and compare the roll speed
The indicator is growing up to 0.12 of the scrollable area size in the corresponding dimension. Additionally the indicator size cannot be more than approximately 0.6 of the texture height (due to some mathematical reasons). Therefore you can also use low texture to limit the maximal indicator size.
Indicator consists of a set of blocks, which are a little bit overlapped sometimes. In order to avoid dirty connections, do not use partially transparent areas around top and bottom sides of the texture. Moreover, prefer fully opaque images which will make the content fade out. This notifies a user that the content continues — actually even better than high contrast scrolling indicator:
In hac habitasse platea dictumst. Mauris in tincidunt tortor. Donec ullamcorper nunc purus, vitae pretium libero ornare eu. Nam porttitor est in tempus posuere. Curabitur eget nisi et orci convallis vehicula malesuada non mauris. Phasellus fermentum maximus lorem, at aliquam nisi ullamcorper eu. Donec feugiat ante metus, et sollicitudin tortor consequat sit amet. Duis posuere risus ut fringilla congue. Pellentesque porta nisl eget ipsum interdum, a lacinia diam ullamcorper.
Donec eget ex malesuada, viverra urna vitae, luctus ex. Mauris pretium hendrerit felis nec dignissim. Integer vitae odio odio. Curabitur vitae mollis neque. Vestibulum eget porta metus. Maecenas ac quam vehicula, gravida est sit amet, hendrerit nulla. Cras viverra velit enim, at viverra nulla tincidunt ut. Fusce vestibulum nunc sit amet vehicula sagittis. Mauris feugiat faucibus elit.
Proin vulputate elit euismod risus vulputate, vel ultrices nunc lacinia. In hac habitasse platea dictumst. Morbi at odio in nisi ornare feugiat vitae in dui. In sed lacus orci. Maecenas mollis mollis pretium. Nam ac ullamcorper enim, nec ultrices urna. Vestibulum vitae metus pharetra, tempus quam a, rhoncus arcu. Curabitur ac orci et turpis accumsan porttitor. Sed et gravida arcu. In posuere fringilla consectetur. Fusce in tortor fringilla, consectetur ante sed, varius tortor. Suspendisse nec quam elit. Vestibulum luctus egestas maximus. Vestibulum elementum sit amet tellus vitae cursus. Quisque hendrerit euismod fringilla.
Sed tempus arcu id velit condimentum, quis malesuada lectus sagittis. Mauris eget leo id risus dapibus mollis vitae non risus. Ut laoreet eu quam in gravida. Suspendisse potenti. Mauris quis tempus mauris, et rhoncus sapien. Mauris dui nunc, eleifend vel vehicula a, interdum eu purus. Quisque nunc diam, dapibus a fringilla in, ultrices in ante. Nam et dapibus nisl. Vivamus faucibus condimentum ipsum, a sagittis elit mollis scelerisque. In a ex vitae odio egestas interdum nec eu lacus. Aenean consequat iaculis tellus, vel malesuada odio gravida sed. Nunc pellentesque nulla aliquam tellus suscipit, eleifend iaculis nisi gravida. Nunc dictum urna id maximus feugiat. Phasellus volutpat molestie erat nec feugiat. Cras vulputate velit id metus volutpat, quis vestibulum orci pulvinar. Nulla et porta dui.
Phasellus dignissim vitae leo at ultrices. Donec fringilla ipsum id neque ultrices, nec efficitur orci laoreet. Curabitur quam libero, suscipit in ex vel, egestas commodo ex. Proin a dolor ut lacus dictum placerat quis vitae risus. Duis eget pellentesque erat, quis maximus arcu. Maecenas lacinia sapien sed odio suscipit, vel rutrum felis ornare. Aenean sagittis urna a justo dictum maximus. Donec condimentum justo nec arcu tristique luctus. Maecenas pellentesque, nunc non aliquet interdum, mi tellus lacinia lacus, dignissim dapibus nibh turpis eget purus. Donec ut lorem id mi scelerisque bibendum vitae et est. Nulla sed tellus facilisis, rhoncus neque id, pulvinar leo. Suspendisse imperdiet ipsum libero, id elementum velit sodales sed. Quisque vel tortor tellus. Aenean egestas non mi at vulputate. Nulla eget tempus augue. Nulla massa ante, blandit vitae quam sed, molestie feugiat nisl.
Aenean consectetur nunc at sapien accumsan, vitae condimentum neque mattis. Proin eget ultrices nunc. Proin auctor volutpat lacus. Donec blandit nulla at ornare tempor. Aenean dictum, dolor sit amet malesuada tristique, sem tortor iaculis nulla, sed mattis justo ipsum at massa. Morbi eleifend, erat a eleifend hendrerit, nibh ipsum mattis magna, sit amet maximus leo magna ac orci. Nullam ultrices, metus ut sollicitudin volutpat, leo metus accumsan dui, sed vestibulum ex est ac erat. Sed placerat finibus quam lobortis eleifend. Aenean facilisis nisl sed fermentum venenatis. Nam accumsan fringilla urna, ac pellentesque mi pellentesque eu. Sed commodo mi sapien, ac hendrerit sem facilisis nec.
Vivamus et efficitur leo, eu viverra ligula. Sed imperdiet sed eros quis rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus vel nunc euismod, pellentesque orci ut, molestie massa. Phasellus magna massa, lacinia sed tortor vitae, aliquet lacinia est. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse ornare erat condimentum, euismod nisi eget, facilisis nisl. Vivamus a turpis lobortis, bibendum orci at, euismod est. Maecenas est leo, congue et ornare at, feugiat at ex. Aliquam ligula dui, scelerisque quis risus ac, malesuada lacinia lorem.
Aliquam eget velit pharetra, viverra metus a, convallis tellus. Praesent ullamcorper fringilla purus, vel sollicitudin ex interdum in. Nullam vitae tincidunt neque. Pellentesque felis dui, consectetur id sagittis vel, dapibus a lacus. Praesent vehicula nisi aliquet diam maximus blandit. Fusce at metus nec sem consectetur eleifend nec ac odio. Suspendisse fringilla, diam venenatis pulvinar posuere, nisi arcu iaculis nisi, eget molestie augue diam vitae arcu. Sed ultrices lacinia risus in congue.
Aliquam hendrerit eleifend neque, a iaculis lacus. Ut id luctus massa. Donec sodales placerat interdum. Nulla dolor libero, lacinia vel ornare at, faucibus vel ipsum. In eu finibus dui. Cras nisi tortor, pharetra nec mollis a, sagittis in ante. Donec fringilla convallis nunc, vitae euismod lacus accumsan id. Etiam vehicula lectus eleifend tincidunt pellentesque. Duis accumsan nunc urna.
Nunc sed nulla sed nunc facilisis tincidunt nec vel nisl. Morbi pellentesque malesuada tellus, sit amet porta urna hendrerit at. Suspendisse sed egestas metus, non efficitur tortor. Pellentesque iaculis, magna ut malesuada sagittis, est eros dignissim felis, ornare facilisis metus nisl sit amet orci. Vestibulum sit amet eleifend nisi, ultricies aliquam libero. Praesent semper mi ultrices congue ullamcorper. Fusce a sem felis. Phasellus nisi odio, pharetra ut metus nec, porta semper massa. Etiam at nunc sed arcu varius posuere a at lorem. Etiam sem nisl, cursus non lacus id, lacinia tempor tortor.
Nam est eros, facilisis sit amet orci ultricies, commodo pellentesque nisl. Donec nec metus dignissim, rhoncus erat vitae, gravida libero. Nunc hendrerit sit amet nibh quis feugiat. Phasellus et finibus massa. Sed congue nibh augue, sit amet cursus velit varius vitae. Donec consequat metus aliquam nibh feugiat consectetur. Cras vel volutpat ex. Quisque lobortis dui orci, a pharetra justo malesuada sit amet. Suspendisse potenti. Nulla facilisi. Curabitur hendrerit tellus tortor, quis facilisis urna fringilla at.
Duis magna ante, pulvinar ac sagittis in, mollis at enim. Integer rhoncus vestibulum leo, in mollis leo laoreet id. Nullam blandit lectus vitae vehicula suscipit. Ut vel posuere ligula. Nullam a tempus sem. Nullam mollis sit amet leo bibendum euismod. Cras faucibus metus sit amet euismod pellentesque. Pellentesque sed eleifend sapien. Vivamus congue lorem eget erat posuere convallis. Curabitur a congue nisl. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aliquam vel pretium magna, venenatis luctus lacus. Aenean ac accumsan augue. Ut consequat lacus vel lectus scelerisque, ut facilisis orci sagittis.
Fusce in auctor massa. Cras a quam eget libero posuere aliquam sed et sapien. Fusce scelerisque laoreet eleifend. Phasellus eget nisi tortor. Cras dignissim eget leo ut pretium. Sed eleifend, massa suscipit interdum bibendum, arcu nibh gravida erat, nec gravida orci est sed orci. Praesent in luctus turpis, in pellentesque tellus. Cras condimentum porta magna, eget sagittis neque. Proin sit amet neque et lectus semper pellentesque quis vel felis.
Vestibulum id odio quis enim eleifend vulputate eget eu orci. Nullam porttitor purus vitae quam ornare, ac finibus nisl laoreet. Suspendisse laoreet porta scelerisque. Quisque at lorem lacus. Suspendisse potenti. Donec volutpat id eros in sodales. In sit amet pulvinar ante. In ornare libero nec orci fermentum malesuada. Vivamus interdum luctus est eget malesuada. Suspendisse potenti.
Nam ut nisl scelerisque tellus rutrum tempor. Duis tristique ullamcorper purus, rutrum varius elit. Mauris pretium malesuada dui, quis tincidunt erat ornare id. Suspendisse fermentum, orci nec feugiat efficitur, ex ipsum mattis tellus, ut egestas risus metus ac risus. Donec vitae tincidunt magna. In nec feugiat nibh. Morbi rutrum sed enim nec aliquam. Praesent enim urna, elementum quis ante tristique, efficitur fringilla velit. Aenean sodales sem a purus blandit lobortis. Phasellus vel purus tellus. Phasellus vel lorem vel purus fermentum vehicula. Mauris ac lectus ullamcorper diam rutrum mollis tempus non ante.
Vestibulum sagittis porta sapien, non posuere lorem vehicula eu. Maecenas viverra placerat leo, quis fermentum purus. Sed pellentesque, nunc quis maximus suscipit, tellus metus elementum elit, nec volutpat dui nisi nec est. Pellentesque id nisl metus. Nulla at suscipit leo, et dictum purus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin maximus, eros nec varius porttitor, ex odio luctus diam, eget viverra ipsum odio at ipsum.
Maecenas sollicitudin egestas nibh, vel dictum mi fringilla quis. Praesent euismod eget neque eu finibus. Vestibulum sit amet malesuada urna. Suspendisse et dapibus justo. Sed molestie mi eu ante tincidunt porttitor. Morbi tincidunt orci sed purus pharetra, nec mattis purus convallis. Suspendisse porttitor porta volutpat. In bibendum nisl sed sem mollis rhoncus. Mauris varius lobortis nulla non dapibus. Sed lacinia enim quam, a condimentum tellus fermentum sed. Etiam quis hendrerit metus. Nam sit amet varius arcu.
Suspendisse dolor magna, lacinia in mauris eget, consectetur aliquet lacus. Donec eget felis eget erat sollicitudin dapibus. Vivamus tincidunt feugiat leo, in sagittis lorem tempor vitae. Quisque molestie, nunc vel molestie pharetra, diam velit dignissim mauris, eget bibendum posuere.
In hac habitasse platea dictumst. Mauris in tincidunt tortor. Donec ullamcorper nunc purus, vitae pretium libero ornare eu. Nam porttitor est in tempus posuere. Curabitur eget nisi et orci convallis vehicula malesuada non mauris. Phasellus fermentum maximus lorem, at aliquam nisi ullamcorper eu. Donec feugiat ante metus, et sollicitudin tortor consequat sit amet. Duis posuere risus ut fringilla congue. Pellentesque porta nisl eget ipsum interdum, a lacinia diam ullamcorper.
Donec eget ex malesuada, viverra urna vitae, luctus ex. Mauris pretium hendrerit felis nec dignissim. Integer vitae odio odio. Curabitur vitae mollis neque. Vestibulum eget porta metus. Maecenas ac quam vehicula, gravida est sit amet, hendrerit nulla. Cras viverra velit enim, at viverra nulla tincidunt ut. Fusce vestibulum nunc sit amet vehicula sagittis. Mauris feugiat faucibus elit.
Proin vulputate elit euismod risus vulputate, vel ultrices nunc lacinia. In hac habitasse platea dictumst. Morbi at odio in nisi ornare feugiat vitae in dui. In sed lacus orci. Maecenas mollis mollis pretium. Nam ac ullamcorper enim, nec ultrices urna. Vestibulum vitae metus pharetra, tempus quam a, rhoncus arcu. Curabitur ac orci et turpis accumsan porttitor. Sed et gravida arcu. In posuere fringilla consectetur. Fusce in tortor fringilla, consectetur ante sed, varius tortor. Suspendisse nec quam elit. Vestibulum luctus egestas maximus. Vestibulum elementum sit amet tellus vitae cursus. Quisque hendrerit euismod fringilla.
Sed tempus arcu id velit condimentum, quis malesuada lectus sagittis. Mauris eget leo id risus dapibus mollis vitae non risus. Ut laoreet eu quam in gravida. Suspendisse potenti. Mauris quis tempus mauris, et rhoncus sapien. Mauris dui nunc, eleifend vel vehicula a, interdum eu purus. Quisque nunc diam, dapibus a fringilla in, ultrices in ante. Nam et dapibus nisl. Vivamus faucibus condimentum ipsum, a sagittis elit mollis scelerisque. In a ex vitae odio egestas interdum nec eu lacus. Aenean consequat iaculis tellus, vel malesuada odio gravida sed. Nunc pellentesque nulla aliquam tellus suscipit, eleifend iaculis nisi gravida. Nunc dictum urna id maximus feugiat. Phasellus volutpat molestie erat nec feugiat. Cras vulputate velit id metus volutpat, quis vestibulum orci pulvinar. Nulla et porta dui.
Phasellus dignissim vitae leo at ultrices. Donec fringilla ipsum id neque ultrices, nec efficitur orci laoreet. Curabitur quam libero, suscipit in ex vel, egestas commodo ex. Proin a dolor ut lacus dictum placerat quis vitae risus. Duis eget pellentesque erat, quis maximus arcu. Maecenas lacinia sapien sed odio suscipit, vel rutrum felis ornare. Aenean sagittis urna a justo dictum maximus. Donec condimentum justo nec arcu tristique luctus. Maecenas pellentesque, nunc non aliquet interdum, mi tellus lacinia lacus, dignissim dapibus nibh turpis eget purus. Donec ut lorem id mi scelerisque bibendum vitae et est. Nulla sed tellus facilisis, rhoncus neque id, pulvinar leo. Suspendisse imperdiet ipsum libero, id elementum velit sodales sed. Quisque vel tortor tellus. Aenean egestas non mi at vulputate. Nulla eget tempus augue. Nulla massa ante, blandit vitae quam sed, molestie feugiat nisl.
Aenean consectetur nunc at sapien accumsan, vitae condimentum neque mattis. Proin eget ultrices nunc. Proin auctor volutpat lacus. Donec blandit nulla at ornare tempor. Aenean dictum, dolor sit amet malesuada tristique, sem tortor iaculis nulla, sed mattis justo ipsum at massa. Morbi eleifend, erat a eleifend hendrerit, nibh ipsum mattis magna, sit amet maximus leo magna ac orci. Nullam ultrices, metus ut sollicitudin volutpat, leo metus accumsan dui, sed vestibulum ex est ac erat. Sed placerat finibus quam lobortis eleifend. Aenean facilisis nisl sed fermentum venenatis. Nam accumsan fringilla urna, ac pellentesque mi pellentesque eu. Sed commodo mi sapien, ac hendrerit sem facilisis nec.
Vivamus et efficitur leo, eu viverra ligula. Sed imperdiet sed eros quis rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus vel nunc euismod, pellentesque orci ut, molestie massa. Phasellus magna massa, lacinia sed tortor vitae, aliquet lacinia est. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse ornare erat condimentum, euismod nisi eget, facilisis nisl. Vivamus a turpis lobortis, bibendum orci at, euismod est. Maecenas est leo, congue et ornare at, feugiat at ex. Aliquam ligula dui, scelerisque quis risus ac, malesuada lacinia lorem.
Aliquam eget velit pharetra, viverra metus a, convallis tellus. Praesent ullamcorper fringilla purus, vel sollicitudin ex interdum in. Nullam vitae tincidunt neque. Pellentesque felis dui, consectetur id sagittis vel, dapibus a lacus. Praesent vehicula nisi aliquet diam maximus blandit. Fusce at metus nec sem consectetur eleifend nec ac odio. Suspendisse fringilla, diam venenatis pulvinar posuere, nisi arcu iaculis nisi, eget molestie augue diam vitae arcu. Sed ultrices lacinia risus in congue.
Aliquam hendrerit eleifend neque, a iaculis lacus. Ut id luctus massa. Donec sodales placerat interdum. Nulla dolor libero, lacinia vel ornare at, faucibus vel ipsum. In eu finibus dui. Cras nisi tortor, pharetra nec mollis a, sagittis in ante. Donec fringilla convallis nunc, vitae euismod lacus accumsan id. Etiam vehicula lectus eleifend tincidunt pellentesque. Duis accumsan nunc urna.
Nunc sed nulla sed nunc facilisis tincidunt nec vel nisl. Morbi pellentesque malesuada tellus, sit amet porta urna hendrerit at. Suspendisse sed egestas metus, non efficitur tortor. Pellentesque iaculis, magna ut malesuada sagittis, est eros dignissim felis, ornare facilisis metus nisl sit amet orci. Vestibulum sit amet eleifend nisi, ultricies aliquam libero. Praesent semper mi ultrices congue ullamcorper. Fusce a sem felis. Phasellus nisi odio, pharetra ut metus nec, porta semper massa. Etiam at nunc sed arcu varius posuere a at lorem. Etiam sem nisl, cursus non lacus id, lacinia tempor tortor.
Nam est eros, facilisis sit amet orci ultricies, commodo pellentesque nisl. Donec nec metus dignissim, rhoncus erat vitae, gravida libero. Nunc hendrerit sit amet nibh quis feugiat. Phasellus et finibus massa. Sed congue nibh augue, sit amet cursus velit varius vitae. Donec consequat metus aliquam nibh feugiat consectetur. Cras vel volutpat ex. Quisque lobortis dui orci, a pharetra justo malesuada sit amet. Suspendisse potenti. Nulla facilisi. Curabitur hendrerit tellus tortor, quis facilisis urna fringilla at.
Duis magna ante, pulvinar ac sagittis in, mollis at enim. Integer rhoncus vestibulum leo, in mollis leo laoreet id. Nullam blandit lectus vitae vehicula suscipit. Ut vel posuere ligula. Nullam a tempus sem. Nullam mollis sit amet leo bibendum euismod. Cras faucibus metus sit amet euismod pellentesque. Pellentesque sed eleifend sapien. Vivamus congue lorem eget erat posuere convallis. Curabitur a congue nisl. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aliquam vel pretium magna, venenatis luctus lacus. Aenean ac accumsan augue. Ut consequat lacus vel lectus scelerisque, ut facilisis orci sagittis.
Fusce in auctor massa. Cras a quam eget libero posuere aliquam sed et sapien. Fusce scelerisque laoreet eleifend. Phasellus eget nisi tortor. Cras dignissim eget leo ut pretium. Sed eleifend, massa suscipit interdum bibendum, arcu nibh gravida erat, nec gravida orci est sed orci. Praesent in luctus turpis, in pellentesque tellus. Cras condimentum porta magna, eget sagittis neque. Proin sit amet neque et lectus semper pellentesque quis vel felis.
Vestibulum id odio quis enim eleifend vulputate eget eu orci. Nullam porttitor purus vitae quam ornare, ac finibus nisl laoreet. Suspendisse laoreet porta scelerisque. Quisque at lorem lacus. Suspendisse potenti. Donec volutpat id eros in sodales. In sit amet pulvinar ante. In ornare libero nec orci fermentum malesuada. Vivamus interdum luctus est eget malesuada. Suspendisse potenti.
Nam ut nisl scelerisque tellus rutrum tempor. Duis tristique ullamcorper purus, rutrum varius elit. Mauris pretium malesuada dui, quis tincidunt erat ornare id. Suspendisse fermentum, orci nec feugiat efficitur, ex ipsum mattis tellus, ut egestas risus metus ac risus. Donec vitae tincidunt magna. In nec feugiat nibh. Morbi rutrum sed enim nec aliquam. Praesent enim urna, elementum quis ante tristique, efficitur fringilla velit. Aenean sodales sem a purus blandit lobortis. Phasellus vel purus tellus. Phasellus vel lorem vel purus fermentum vehicula. Mauris ac lectus ullamcorper diam rutrum mollis tempus non ante.
Vestibulum sagittis porta sapien, non posuere lorem vehicula eu. Maecenas viverra placerat leo, quis fermentum purus. Sed pellentesque, nunc quis maximus suscipit, tellus metus elementum elit, nec volutpat dui nisi nec est. Pellentesque id nisl metus. Nulla at suscipit leo, et dictum purus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin maximus, eros nec varius porttitor, ex odio luctus diam, eget viverra ipsum odio at ipsum.
Maecenas sollicitudin egestas nibh, vel dictum mi fringilla quis. Praesent euismod eget neque eu finibus. Vestibulum sit amet malesuada urna. Suspendisse et dapibus justo. Sed molestie mi eu ante tincidunt porttitor. Morbi tincidunt orci sed purus pharetra, nec mattis purus convallis. Suspendisse porttitor porta volutpat. In bibendum nisl sed sem mollis rhoncus. Mauris varius lobortis nulla non dapibus. Sed lacinia enim quam, a condimentum tellus fermentum sed. Etiam quis hendrerit metus. Nam sit amet varius arcu.
Suspendisse dolor magna, lacinia in mauris eget, consectetur aliquet lacus. Donec eget felis eget erat sollicitudin dapibus. Vivamus tincidunt feugiat leo, in sagittis lorem tempor vitae. Quisque molestie, nunc vel molestie pharetra, diam velit dignissim mauris, eget bibendum posuere.
In hac habitasse platea dictumst. Mauris in tincidunt tortor. Donec ullamcorper nunc purus, vitae pretium libero ornare eu. Nam porttitor est in tempus posuere. Curabitur eget nisi et orci convallis vehicula malesuada non mauris. Phasellus fermentum maximus lorem, at aliquam nisi ullamcorper eu. Donec feugiat ante metus, et sollicitudin tortor consequat sit amet. Duis posuere risus ut fringilla congue. Pellentesque porta nisl eget ipsum interdum, a lacinia diam ullamcorper.
Donec eget ex malesuada, viverra urna vitae, luctus ex. Mauris pretium hendrerit felis nec dignissim. Integer vitae odio odio. Curabitur vitae mollis neque. Vestibulum eget porta metus. Maecenas ac quam vehicula, gravida est sit amet, hendrerit nulla. Cras viverra velit enim, at viverra nulla tincidunt ut. Fusce vestibulum nunc sit amet vehicula sagittis. Mauris feugiat faucibus elit.
Proin vulputate elit euismod risus vulputate, vel ultrices nunc lacinia. In hac habitasse platea dictumst. Morbi at odio in nisi ornare feugiat vitae in dui. In sed lacus orci. Maecenas mollis mollis pretium. Nam ac ullamcorper enim, nec ultrices urna. Vestibulum vitae metus pharetra, tempus quam a, rhoncus arcu. Curabitur ac orci et turpis accumsan porttitor. Sed et gravida arcu. In posuere fringilla consectetur. Fusce in tortor fringilla, consectetur ante sed, varius tortor. Suspendisse nec quam elit. Vestibulum luctus egestas maximus. Vestibulum elementum sit amet tellus vitae cursus. Quisque hendrerit euismod fringilla.
Sed tempus arcu id velit condimentum, quis malesuada lectus sagittis. Mauris eget leo id risus dapibus mollis vitae non risus. Ut laoreet eu quam in gravida. Suspendisse potenti. Mauris quis tempus mauris, et rhoncus sapien. Mauris dui nunc, eleifend vel vehicula a, interdum eu purus. Quisque nunc diam, dapibus a fringilla in, ultrices in ante. Nam et dapibus nisl. Vivamus faucibus condimentum ipsum, a sagittis elit mollis scelerisque. In a ex vitae odio egestas interdum nec eu lacus. Aenean consequat iaculis tellus, vel malesuada odio gravida sed. Nunc pellentesque nulla aliquam tellus suscipit, eleifend iaculis nisi gravida. Nunc dictum urna id maximus feugiat. Phasellus volutpat molestie erat nec feugiat. Cras vulputate velit id metus volutpat, quis vestibulum orci pulvinar. Nulla et porta dui.
Phasellus dignissim vitae leo at ultrices. Donec fringilla ipsum id neque ultrices, nec efficitur orci laoreet. Curabitur quam libero, suscipit in ex vel, egestas commodo ex. Proin a dolor ut lacus dictum placerat quis vitae risus. Duis eget pellentesque erat, quis maximus arcu. Maecenas lacinia sapien sed odio suscipit, vel rutrum felis ornare. Aenean sagittis urna a justo dictum maximus. Donec condimentum justo nec arcu tristique luctus. Maecenas pellentesque, nunc non aliquet interdum, mi tellus lacinia lacus, dignissim dapibus nibh turpis eget purus. Donec ut lorem id mi scelerisque bibendum vitae et est. Nulla sed tellus facilisis, rhoncus neque id, pulvinar leo. Suspendisse imperdiet ipsum libero, id elementum velit sodales sed. Quisque vel tortor tellus. Aenean egestas non mi at vulputate. Nulla eget tempus augue. Nulla massa ante, blandit vitae quam sed, molestie feugiat nisl.
Aenean consectetur nunc at sapien accumsan, vitae condimentum neque mattis. Proin eget ultrices nunc. Proin auctor volutpat lacus. Donec blandit nulla at ornare tempor. Aenean dictum, dolor sit amet malesuada tristique, sem tortor iaculis nulla, sed mattis justo ipsum at massa. Morbi eleifend, erat a eleifend hendrerit, nibh ipsum mattis magna, sit amet maximus leo magna ac orci. Nullam ultrices, metus ut sollicitudin volutpat, leo metus accumsan dui, sed vestibulum ex est ac erat. Sed placerat finibus quam lobortis eleifend. Aenean facilisis nisl sed fermentum venenatis. Nam accumsan fringilla urna, ac pellentesque mi pellentesque eu. Sed commodo mi sapien, ac hendrerit sem facilisis nec.
Vivamus et efficitur leo, eu viverra ligula. Sed imperdiet sed eros quis rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus vel nunc euismod, pellentesque orci ut, molestie massa. Phasellus magna massa, lacinia sed tortor vitae, aliquet lacinia est. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse ornare erat condimentum, euismod nisi eget, facilisis nisl. Vivamus a turpis lobortis, bibendum orci at, euismod est. Maecenas est leo, congue et ornare at, feugiat at ex. Aliquam ligula dui, scelerisque quis risus ac, malesuada lacinia lorem.
Aliquam eget velit pharetra, viverra metus a, convallis tellus. Praesent ullamcorper fringilla purus, vel sollicitudin ex interdum in. Nullam vitae tincidunt neque. Pellentesque felis dui, consectetur id sagittis vel, dapibus a lacus. Praesent vehicula nisi aliquet diam maximus blandit. Fusce at metus nec sem consectetur eleifend nec ac odio. Suspendisse fringilla, diam venenatis pulvinar posuere, nisi arcu iaculis nisi, eget molestie augue diam vitae arcu. Sed ultrices lacinia risus in congue.
Aliquam hendrerit eleifend neque, a iaculis lacus. Ut id luctus massa. Donec sodales placerat interdum. Nulla dolor libero, lacinia vel ornare at, faucibus vel ipsum. In eu finibus dui. Cras nisi tortor, pharetra nec mollis a, sagittis in ante. Donec fringilla convallis nunc, vitae euismod lacus accumsan id. Etiam vehicula lectus eleifend tincidunt pellentesque. Duis accumsan nunc urna.
Nunc sed nulla sed nunc facilisis tincidunt nec vel nisl. Morbi pellentesque malesuada tellus, sit amet porta urna hendrerit at. Suspendisse sed egestas metus, non efficitur tortor. Pellentesque iaculis, magna ut malesuada sagittis, est eros dignissim felis, ornare facilisis metus nisl sit amet orci. Vestibulum sit amet eleifend nisi, ultricies aliquam libero. Praesent semper mi ultrices congue ullamcorper. Fusce a sem felis. Phasellus nisi odio, pharetra ut metus nec, porta semper massa. Etiam at nunc sed arcu varius posuere a at lorem. Etiam sem nisl, cursus non lacus id, lacinia tempor tortor.
Nam est eros, facilisis sit amet orci ultricies, commodo pellentesque nisl. Donec nec metus dignissim, rhoncus erat vitae, gravida libero. Nunc hendrerit sit amet nibh quis feugiat. Phasellus et finibus massa. Sed congue nibh augue, sit amet cursus velit varius vitae. Donec consequat metus aliquam nibh feugiat consectetur. Cras vel volutpat ex. Quisque lobortis dui orci, a pharetra justo malesuada sit amet. Suspendisse potenti. Nulla facilisi. Curabitur hendrerit tellus tortor, quis facilisis urna fringilla at.
Duis magna ante, pulvinar ac sagittis in, mollis at enim. Integer rhoncus vestibulum leo, in mollis leo laoreet id. Nullam blandit lectus vitae vehicula suscipit. Ut vel posuere ligula. Nullam a tempus sem. Nullam mollis sit amet leo bibendum euismod. Cras faucibus metus sit amet euismod pellentesque. Pellentesque sed eleifend sapien. Vivamus congue lorem eget erat posuere convallis. Curabitur a congue nisl. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aliquam vel pretium magna, venenatis luctus lacus. Aenean ac accumsan augue. Ut consequat lacus vel lectus scelerisque, ut facilisis orci sagittis.
Fusce in auctor massa. Cras a quam eget libero posuere aliquam sed et sapien. Fusce scelerisque laoreet eleifend. Phasellus eget nisi tortor. Cras dignissim eget leo ut pretium. Sed eleifend, massa suscipit interdum bibendum, arcu nibh gravida erat, nec gravida orci est sed orci. Praesent in luctus turpis, in pellentesque tellus. Cras condimentum porta magna, eget sagittis neque. Proin sit amet neque et lectus semper pellentesque quis vel felis.
Vestibulum id odio quis enim eleifend vulputate eget eu orci. Nullam porttitor purus vitae quam ornare, ac finibus nisl laoreet. Suspendisse laoreet porta scelerisque. Quisque at lorem lacus. Suspendisse potenti. Donec volutpat id eros in sodales. In sit amet pulvinar ante. In ornare libero nec orci fermentum malesuada. Vivamus interdum luctus est eget malesuada. Suspendisse potenti.
Nam ut nisl scelerisque tellus rutrum tempor. Duis tristique ullamcorper purus, rutrum varius elit. Mauris pretium malesuada dui, quis tincidunt erat ornare id. Suspendisse fermentum, orci nec feugiat efficitur, ex ipsum mattis tellus, ut egestas risus metus ac risus. Donec vitae tincidunt magna. In nec feugiat nibh. Morbi rutrum sed enim nec aliquam. Praesent enim urna, elementum quis ante tristique, efficitur fringilla velit. Aenean sodales sem a purus blandit lobortis. Phasellus vel purus tellus. Phasellus vel lorem vel purus fermentum vehicula. Mauris ac lectus ullamcorper diam rutrum mollis tempus non ante.
Vestibulum sagittis porta sapien, non posuere lorem vehicula eu. Maecenas viverra placerat leo, quis fermentum purus. Sed pellentesque, nunc quis maximus suscipit, tellus metus elementum elit, nec volutpat dui nisi nec est. Pellentesque id nisl metus. Nulla at suscipit leo, et dictum purus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin maximus, eros nec varius porttitor, ex odio luctus diam, eget viverra ipsum odio at ipsum.
Maecenas sollicitudin egestas nibh, vel dictum mi fringilla quis. Praesent euismod eget neque eu finibus. Vestibulum sit amet malesuada urna. Suspendisse et dapibus justo. Sed molestie mi eu ante tincidunt porttitor. Morbi tincidunt orci sed purus pharetra, nec mattis purus convallis. Suspendisse porttitor porta volutpat. In bibendum nisl sed sem mollis rhoncus. Mauris varius lobortis nulla non dapibus. Sed lacinia enim quam, a condimentum tellus fermentum sed. Etiam quis hendrerit metus. Nam sit amet varius arcu.
Suspendisse dolor magna, lacinia in mauris eget, consectetur aliquet lacus. Donec eget felis eget erat sollicitudin dapibus. Vivamus tincidunt feugiat leo, in sagittis lorem tempor vitae. Quisque molestie, nunc vel molestie pharetra, diam velit dignissim mauris, eget bibendum posuere.
In hac habitasse platea dictumst. Mauris in tincidunt tortor. Donec ullamcorper nunc purus, vitae pretium libero ornare eu. Nam porttitor est in tempus posuere. Curabitur eget nisi et orci convallis vehicula malesuada non mauris. Phasellus fermentum maximus lorem, at aliquam nisi ullamcorper eu. Donec feugiat ante metus, et sollicitudin tortor consequat sit amet. Duis posuere risus ut fringilla congue. Pellentesque porta nisl eget ipsum interdum, a lacinia diam ullamcorper.
Donec eget ex malesuada, viverra urna vitae, luctus ex. Mauris pretium hendrerit felis nec dignissim. Integer vitae odio odio. Curabitur vitae mollis neque. Vestibulum eget porta metus. Maecenas ac quam vehicula, gravida est sit amet, hendrerit nulla. Cras viverra velit enim, at viverra nulla tincidunt ut. Fusce vestibulum nunc sit amet vehicula sagittis. Mauris feugiat faucibus elit.
Proin vulputate elit euismod risus vulputate, vel ultrices nunc lacinia. In hac habitasse platea dictumst. Morbi at odio in nisi ornare feugiat vitae in dui. In sed lacus orci. Maecenas mollis mollis pretium. Nam ac ullamcorper enim, nec ultrices urna. Vestibulum vitae metus pharetra, tempus quam a, rhoncus arcu. Curabitur ac orci et turpis accumsan porttitor. Sed et gravida arcu. In posuere fringilla consectetur. Fusce in tortor fringilla, consectetur ante sed, varius tortor. Suspendisse nec quam elit. Vestibulum luctus egestas maximus. Vestibulum elementum sit amet tellus vitae cursus. Quisque hendrerit euismod fringilla.
Sed tempus arcu id velit condimentum, quis malesuada lectus sagittis. Mauris eget leo id risus dapibus mollis vitae non risus. Ut laoreet eu quam in gravida. Suspendisse potenti. Mauris quis tempus mauris, et rhoncus sapien. Mauris dui nunc, eleifend vel vehicula a, interdum eu purus. Quisque nunc diam, dapibus a fringilla in, ultrices in ante. Nam et dapibus nisl. Vivamus faucibus condimentum ipsum, a sagittis elit mollis scelerisque. In a ex vitae odio egestas interdum nec eu lacus. Aenean consequat iaculis tellus, vel malesuada odio gravida sed. Nunc pellentesque nulla aliquam tellus suscipit, eleifend iaculis nisi gravida. Nunc dictum urna id maximus feugiat. Phasellus volutpat molestie erat nec feugiat. Cras vulputate velit id metus volutpat, quis vestibulum orci pulvinar. Nulla et porta dui.
Phasellus dignissim vitae leo at ultrices. Donec fringilla ipsum id neque ultrices, nec efficitur orci laoreet. Curabitur quam libero, suscipit in ex vel, egestas commodo ex. Proin a dolor ut lacus dictum placerat quis vitae risus. Duis eget pellentesque erat, quis maximus arcu. Maecenas lacinia sapien sed odio suscipit, vel rutrum felis ornare. Aenean sagittis urna a justo dictum maximus. Donec condimentum justo nec arcu tristique luctus. Maecenas pellentesque, nunc non aliquet interdum, mi tellus lacinia lacus, dignissim dapibus nibh turpis eget purus. Donec ut lorem id mi scelerisque bibendum vitae et est. Nulla sed tellus facilisis, rhoncus neque id, pulvinar leo. Suspendisse imperdiet ipsum libero, id elementum velit sodales sed. Quisque vel tortor tellus. Aenean egestas non mi at vulputate. Nulla eget tempus augue. Nulla massa ante, blandit vitae quam sed, molestie feugiat nisl.
Aenean consectetur nunc at sapien accumsan, vitae condimentum neque mattis. Proin eget ultrices nunc. Proin auctor volutpat lacus. Donec blandit nulla at ornare tempor. Aenean dictum, dolor sit amet malesuada tristique, sem tortor iaculis nulla, sed mattis justo ipsum at massa. Morbi eleifend, erat a eleifend hendrerit, nibh ipsum mattis magna, sit amet maximus leo magna ac orci. Nullam ultrices, metus ut sollicitudin volutpat, leo metus accumsan dui, sed vestibulum ex est ac erat. Sed placerat finibus quam lobortis eleifend. Aenean facilisis nisl sed fermentum venenatis. Nam accumsan fringilla urna, ac pellentesque mi pellentesque eu. Sed commodo mi sapien, ac hendrerit sem facilisis nec.
Vivamus et efficitur leo, eu viverra ligula. Sed imperdiet sed eros quis rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus vel nunc euismod, pellentesque orci ut, molestie massa. Phasellus magna massa, lacinia sed tortor vitae, aliquet lacinia est. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse ornare erat condimentum, euismod nisi eget, facilisis nisl. Vivamus a turpis lobortis, bibendum orci at, euismod est. Maecenas est leo, congue et ornare at, feugiat at ex. Aliquam ligula dui, scelerisque quis risus ac, malesuada lacinia lorem.
Aliquam eget velit pharetra, viverra metus a, convallis tellus. Praesent ullamcorper fringilla purus, vel sollicitudin ex interdum in. Nullam vitae tincidunt neque. Pellentesque felis dui, consectetur id sagittis vel, dapibus a lacus. Praesent vehicula nisi aliquet diam maximus blandit. Fusce at metus nec sem consectetur eleifend nec ac odio. Suspendisse fringilla, diam venenatis pulvinar posuere, nisi arcu iaculis nisi, eget molestie augue diam vitae arcu. Sed ultrices lacinia risus in congue.
Aliquam hendrerit eleifend neque, a iaculis lacus. Ut id luctus massa. Donec sodales placerat interdum. Nulla dolor libero, lacinia vel ornare at, faucibus vel ipsum. In eu finibus dui. Cras nisi tortor, pharetra nec mollis a, sagittis in ante. Donec fringilla convallis nunc, vitae euismod lacus accumsan id. Etiam vehicula lectus eleifend tincidunt pellentesque. Duis accumsan nunc urna.
Nunc sed nulla sed nunc facilisis tincidunt nec vel nisl. Morbi pellentesque malesuada tellus, sit amet porta urna hendrerit at. Suspendisse sed egestas metus, non efficitur tortor. Pellentesque iaculis, magna ut malesuada sagittis, est eros dignissim felis, ornare facilisis metus nisl sit amet orci. Vestibulum sit amet eleifend nisi, ultricies aliquam libero. Praesent semper mi ultrices congue ullamcorper. Fusce a sem felis. Phasellus nisi odio, pharetra ut metus nec, porta semper massa. Etiam at nunc sed arcu varius posuere a at lorem. Etiam sem nisl, cursus non lacus id, lacinia tempor tortor.
Nam est eros, facilisis sit amet orci ultricies, commodo pellentesque nisl. Donec nec metus dignissim, rhoncus erat vitae, gravida libero. Nunc hendrerit sit amet nibh quis feugiat. Phasellus et finibus massa. Sed congue nibh augue, sit amet cursus velit varius vitae. Donec consequat metus aliquam nibh feugiat consectetur. Cras vel volutpat ex. Quisque lobortis dui orci, a pharetra justo malesuada sit amet. Suspendisse potenti. Nulla facilisi. Curabitur hendrerit tellus tortor, quis facilisis urna fringilla at.
Duis magna ante, pulvinar ac sagittis in, mollis at enim. Integer rhoncus vestibulum leo, in mollis leo laoreet id. Nullam blandit lectus vitae vehicula suscipit. Ut vel posuere ligula. Nullam a tempus sem. Nullam mollis sit amet leo bibendum euismod. Cras faucibus metus sit amet euismod pellentesque. Pellentesque sed eleifend sapien. Vivamus congue lorem eget erat posuere convallis. Curabitur a congue nisl. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aliquam vel pretium magna, venenatis luctus lacus. Aenean ac accumsan augue. Ut consequat lacus vel lectus scelerisque, ut facilisis orci sagittis.
Fusce in auctor massa. Cras a quam eget libero posuere aliquam sed et sapien. Fusce scelerisque laoreet eleifend. Phasellus eget nisi tortor. Cras dignissim eget leo ut pretium. Sed eleifend, massa suscipit interdum bibendum, arcu nibh gravida erat, nec gravida orci est sed orci. Praesent in luctus turpis, in pellentesque tellus. Cras condimentum porta magna, eget sagittis neque. Proin sit amet neque et lectus semper pellentesque quis vel felis.
Vestibulum id odio quis enim eleifend vulputate eget eu orci. Nullam porttitor purus vitae quam ornare, ac finibus nisl laoreet. Suspendisse laoreet porta scelerisque. Quisque at lorem lacus. Suspendisse potenti. Donec volutpat id eros in sodales. In sit amet pulvinar ante. In ornare libero nec orci fermentum malesuada. Vivamus interdum luctus est eget malesuada. Suspendisse potenti.
Nam ut nisl scelerisque tellus rutrum tempor. Duis tristique ullamcorper purus, rutrum varius elit. Mauris pretium malesuada dui, quis tincidunt erat ornare id. Suspendisse fermentum, orci nec feugiat efficitur, ex ipsum mattis tellus, ut egestas risus metus ac risus. Donec vitae tincidunt magna. In nec feugiat nibh. Morbi rutrum sed enim nec aliquam. Praesent enim urna, elementum quis ante tristique, efficitur fringilla velit. Aenean sodales sem a purus blandit lobortis. Phasellus vel purus tellus. Phasellus vel lorem vel purus fermentum vehicula. Mauris ac lectus ullamcorper diam rutrum mollis tempus non ante.
Vestibulum sagittis porta sapien, non posuere lorem vehicula eu. Maecenas viverra placerat leo, quis fermentum purus. Sed pellentesque, nunc quis maximus suscipit, tellus metus elementum elit, nec volutpat dui nisi nec est. Pellentesque id nisl metus. Nulla at suscipit leo, et dictum purus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin maximus, eros nec varius porttitor, ex odio luctus diam, eget viverra ipsum odio at ipsum.
Maecenas sollicitudin egestas nibh, vel dictum mi fringilla quis. Praesent euismod eget neque eu finibus. Vestibulum sit amet malesuada urna. Suspendisse et dapibus justo. Sed molestie mi eu ante tincidunt porttitor. Morbi tincidunt orci sed purus pharetra, nec mattis purus convallis. Suspendisse porttitor porta volutpat. In bibendum nisl sed sem mollis rhoncus. Mauris varius lobortis nulla non dapibus. Sed lacinia enim quam, a condimentum tellus fermentum sed. Etiam quis hendrerit metus. Nam sit amet varius arcu.
Suspendisse dolor magna, lacinia in mauris eget, consectetur aliquet lacus. Donec eget felis eget erat sollicitudin dapibus. Vivamus tincidunt feugiat leo, in sagittis lorem tempor vitae. Quisque molestie, nunc vel molestie pharetra, diam velit dignissim mauris, eget bibendum posuere.
Instead of using transparency, use the background of the scrollable content — the indicator still looks transparent, but the content is fading out additionally.
Images containing high-contrast shapes or making high-contrast with the content area, should be avoided. Too much animation during scrolling may distract user so that he looses the focus.
The mentioned scrollImg attribute is used for all sides by default, but you may specify different texture for a particular side using scrollImgNorth, scrollImgSouth, scrollImgEast and scrollImgWest attributes:
<div class=intence scrollImg=texture.png scrollImgNorth=north.png> Big text goes here... </div>
— use north.png for the top side, and tetxure.png for every other side
As shown in the examples above, there is a special maximal mode to be activated in case of infinite scrolling or dynamically appended content (when it is not known in advance how much of content is still to be added). Such behaviour of an indicator is triggered by the scrollInfiniteNorth, scrollInfiniteSouth, scrollInfiniteWest and scrollInfiniteEast attributes, for instance:
<div id=myElem class=intence scrollImg=texture.png scrollInfiniteSouth> Big text goes here... </div>
— the bottom side will always be in maximal mode, regardles of how much is it to scroll yet
After the last piece of content is delivered and appended to the scrollable area, remove the attribute programmatically:
var elem = document.getElementById('myElem'); elem.removeAttribute('scrollInfiniteSouth');
This will smoothly decrease the indicator to the proper size reflecting the amount of remaining content (this does not happen instantly upon the attribute removal, but upon the next act of scrolling instead).
If a browser is too old, intence is not enabled, and will not change anythig on the page. You can determine if this is the case by checking the intence.enabled property — it contains true if intence works, and false otherwise.
Upon the indicator is created for an element, its internal structure is rebuilt in order to hide the scrollbars and create the indicator. The original element does not actually perform scrolling anymore, so if you need to operate the scrolling programmatically (to find out the current scrolling position, or to change it), you can find the actual scroller element at the .scroller property of the original element:
// this will not work // document.getElementById('myElem').scrollTop; // use this instead document.getElementById('myElem').scroller.scrollTop;
The scroller property is available even in case if intence is disabled (in this case it simply points to the element itself), so there is no need to additionally check the intence.enabled flag.
Finally if you add (or remove) the intence class to the element dynamically (or after the page load), notify intence so that it creates / removes indicators for the respective elements:
intence.reset();
As already mentioned, intence splits the issues of scrolling indication, and scrolling control. Namely, intence is only an indicator, and does not provide elements to control the scrolling position — instead it is supposed to be solved by a developer for a particular application.
Think on which kind of navigation a human needs. In some cases it might probably be enough to simply rely on a mouse wheel or a touchscreen. But it will likely be convenient for a human to have something additional — slider buttons for an image gallery, or a content preview with the detailed position designated, like in Sublime Text.
Here are some ideas. Add an opportunity to scroll the content with a click-and-hold style using dragscroll library (this is how areas on this page can be scrolled). Create an interactive navigation menu which reflects the scrolling state relatively to the page sections — this can be done with the viewport.js library (the menu on this page uses that library, also have a look at some addititonal examples). Use natural scroll if your navigation component scrolls the viewport (by clicking on the menu item, for instance).
If you are going to create a library which provides some controls for scrolling to be used along with intence, do not cover the internal content of a scrollable area, or the intence indicator. The indicator is currently transparent for mouse events, and should remain like this (otherwise people will consider the controls as being part of intence and will be confused by it only working in some applications). Put the controls outside of the area, and not inside it. Do not recreate the scrollbar.
end of March 2015, Munich