My Code works for 1 canvas. But I need this implementation to work for 2 of canvas.
So I tried
var SIGNATURE_2 = new CLIPBOARD_CLASS("signatureCanvas2", true);
The problem is that this always pastes the image in the first canvas, I just need to press Ctrl+V.
How do I paste ONLY when the canvas is focused or hovered?
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copy paste Image to Canvas
////////////////////////////////////////////////////////////////////////////////////////////////////////////
var SIGNATURE = new CLIPBOARD_CLASS("signatureCanvas", true);
var SIGNATURE_2 = new CLIPBOARD_CLASS("signatureCanvas2", true);
/**
* image pasting into canvas
*
* #param {string} canvas_id - canvas id
* #param {boolean} autoresize - if canvas will be resized
*/
function CLIPBOARD_CLASS(canvas_id, autoresize) {
var _self = this;
var canvas = document.getElementById(canvas_id);
var ctx = document.getElementById(canvas_id).getContext("2d");
var ctrl_pressed = false;
var command_pressed = false;
var paste_event_support;
var pasteCatcher;
//handlers
document.addEventListener('keydown', function (e) {
_self.on_keyboard_action(e);
}, false); //firefox fix
document.addEventListener('keyup', function (e) {
_self.on_keyboardup_action(e);
}, false); //firefox fix
document.addEventListener('paste', function (e) {
_self.paste_auto(e);
}, false); //official paste handler
//constructor - we ignore security checks here
this.init = function () {
pasteCatcher = document.createElement("div");
pasteCatcher.setAttribute("id", "paste_ff");
pasteCatcher.setAttribute("contenteditable", "");
pasteCatcher.style.cssText = 'opacity:0;position:fixed;top:0px;left:0px;width:10px;margin-left:-20px;';
document.body.appendChild(pasteCatcher);
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (paste_event_support === true || ctrl_pressed == false || mutation.type != 'childList'){
//we already got data in paste_auto()
return true;
}
//if paste handle failed - capture pasted object manually
if(mutation.addedNodes.length == 1) {
if (mutation.addedNodes[0].src != undefined) {
//image
_self.paste_createImage(mutation.addedNodes[0].src);
}
//register cleanup after some time.
setTimeout(function () {
pasteCatcher.innerHTML = '';
}, 20);
}
});
});
var target = document.getElementById('paste_ff');
var config = { attributes: true, childList: true, characterData: true };
observer.observe(target, config);
}();
//default paste action
this.paste_auto = function (e) {
paste_event_support = false;
if(pasteCatcher != undefined){
pasteCatcher.innerHTML = '';
}
if (e.clipboardData) {
var items = e.clipboardData.items;
if (items) {
paste_event_support = true;
//access data directly
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") !== -1) {
//image
var blob = items[i].getAsFile();
var URLObj = window.URL || window.webkitURL;
var source = URLObj.createObjectURL(blob);
this.paste_createImage(source);
}
}
e.preventDefault();
}
else {
//wait for DOMSubtreeModified event
}
}
};
//on keyboard press
this.on_keyboard_action = function (event) {
var k = event.keyCode;
//ctrl
if (k == 17 || event.metaKey || event.ctrlKey) {
if (ctrl_pressed == false)
ctrl_pressed = true;
}
//v
if (k == 86) {
if (document.activeElement != undefined && document.activeElement.type == 'text') {
//let user paste into some input
return false;
}
if (ctrl_pressed == true && pasteCatcher != undefined){
pasteCatcher.focus();
}
}
};
//on kaybord release
this.on_keyboardup_action = function (event) {
//ctrl
if (event.ctrlKey == false && ctrl_pressed == true) {
ctrl_pressed = false;
}
//command
else if(event.metaKey == false && command_pressed == true){
command_pressed = false;
ctrl_pressed = false;
}
};
//draw pasted image to canvas
this.paste_createImage = function (source) {
var pastedImage = new Image();
pastedImage.onload = function () {
if(autoresize == true){
//resize
canvas.width = pastedImage.width;
canvas.height = pastedImage.height;
}
else{
//clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
ctx.drawImage(pastedImage, 0, 0);
};
pastedImage.src = source;
};
}
.signatureCanvas {
border:1px solid #027C8C;
width: 100%;
max-height:200px;
}
<canvas id="signatureCanvas" class="signatureCanvas"></canvas>
<canvas id="signatureCanvas2" class="signatureCanvas"></canvas>
PS: Please just open snipping tool on windows and copy paste an image to test
Detect if mouse is over canvas, and store it in a variable.
var over_canvas=false;
document.getElementById("signatureCanvas").addEventListener("mouseover", function (i) {
over_canvas=true;
});
document.getElementById("signatureCanvas").addEventListener("mouseout", function (i) {
over_canvas=false;
});
When pasting, check if mouse is over canvas by changing your paste function to:
document.addEventListener('paste', function (e) {
if (over_canvas){
_self.paste_auto(e);
}
}, false);
Related
I have below code for dragscroll which runs automatically when page load.
But I want to call this function manually because I'm uppending the html using DOM element.
I have tried with window.factory as well as window.reset but it is not working for me.
My Javascript module file:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
factory((root.dragscroll = {}));
}
}(this, function (exports) {
var _window = window;
var _document = document;
var mousemove = 'mousemove';
var mouseup = 'mouseup';
var mousedown = 'mousedown';
var EventListener = 'EventListener';
var addEventListener = 'add'+EventListener;
var removeEventListener = 'remove'+EventListener;
var newScrollX, newScrollY;
var dragged = [];
var reset = function(i, el) {
for (i = 0; i < dragged.length;)
{
<some code>
}
// cloning into array since HTMLCollection is updated dynamically
dragged = [].slice.call(_document.getElementsByClassName('dragscroll'));
for (i = 0; i < dragged.length;)
{
<some code>
}, 0
);
_window[addEventListener](
mouseup, cont.mu = function() {pushed = 0;}, 0
);
_window[addEventListener](
mousemove,
cont.mm = function(e) {
if (pushed) {
(scroller = el.scroller||el).scrollLeft -=
newScrollX = (- lastClientX + (lastClientX=e.clientX));
scroller.scrollTop -=
newScrollY = (- lastClientY + (lastClientY=e.clientY));
if (el == _document.body) {
(scroller = _document.documentElement).scrollLeft -= newScrollX;
scroller.scrollTop -= newScrollY;
}
}
}, 0
);
})(dragged[i++]);
}
}
if (_document.readyState == 'complete') {
reset();
} else {
_window[addEventListener]('load', reset, 0);
}
exports.reset = reset;
}));
})
I want to call above function manually.
Can you try with
window.dragscroll.reset();
this will call your reset function manually.
Let me know if it helps.
This looks like a standard JavaScript module that exports a reset() method. Depending on your environment you can load this module, e.g with CommonJS it would be
const module = require('name/path/of_your_module_file');
and then to call it when the DOM load is complete with jQuery:
$(() => {
module.reset();
});
I have a onMouseDownEssence() and onMouseUpEssence() function for an HTML element, how to check if onMouseDownEssence() is called every time before calling onMouseUpEssence() to ensure I get the correct mouse down position?
Here is mousedown function:
var mouseDownIndex = -1;
function onMouseDownEssence(downIndex, e, className) {
dragTarget = e.target;
holdStarter = new Date().valueOf();
mouseDownIndex = downIndex;
}
Here is mouseup function:
function onMouseUpEssence(upIndex, e, className) {
var el = e.target;
var holdActive = (new Date().valueOf() - holdStarter) > holdDelay;
if (holdActive) {
var thisUpTargetIndex = el.getAttribute("name");
if (lastUpTargetIndex != null && thisUpTargetIndex != lastUpTargetIndex) {
// console.log("double drag done");
el.removeAttribute(dbl);
lastUpTargetIndex = null;
var selectedText = clickDragAutoExpand(mouseDownIndex, upIndex,
className);
} else {
// console.log("drag done");
var selectedText = clickDragAutoExpand(mouseDownIndex, upIndex,
className);
}
holdActive = false;
} else if (el.getAttribute(dbl) == null) {
el.setAttribute(dbl, 1);
setTimeout(
function() {
if (el.getAttribute(dbl) == 1 && !dragTarget) {
if (e.button === 0) {
// console.log("single clicked ");
el.removeAttribute(dbl);
var selectedText = clickAutoExpand(upIndex,
className);
}
} else {
if (el.getAttribute(dbl) != null)
lastUpTargetIndex = el.getAttribute("name");
}
}, dblDelay);
} else {
// console.log("double clicked");
el.removeAttribute(dbl);
var selectedText = clickAutoExpand(upIndex, className);
}
dragTarget = null;
}
My approach would be to keep a track of whether mouseDownEssence() was called. And if not, call it before proceeding further. This approach would work somewhat as below. It would work differently for asynchronous functions but mouseDownEssence() seems to be a synchronous function.
let isMouseDownEssenceCalled = false;
function mouseDownEssence() {
isMouseDownEssenceCalled = true;
...
}
function mouseUpEssence() {
if (!isMouseDownEssenceCalled) {
mouseDownEssence()
}
...
isMouseDownEssenceCalled = false;
}
I am making a javascript game, using Canvas. It works well superficially, but "Uncaught TypeError: game_state.Update is not a function" keeps going. I cannot know the reason for all day...How can I solve the problem?
error image1, error image2
Suspected files are below.
gfw.js
function onGameInit()
{
document.title = "Lion Travel";
GAME_FPS = 30;
debugSystem.debugMode = true;
//resourcePreLoading
resourcePreLoader.AddImage("/.c9/img/title_background.png");
resourcePreLoader.AddImage("/.c9/img/title_start_off.png");
resourcePreLoader.AddImage("/.c9/img/title_start_on.png");
resourcePreLoader.AddImage("/.c9/img/title_ranking_off.png");
resourcePreLoader.AddImage("/.c9/img/title_ranking_on.png");
resourcePreLoader.AddImage("/.c9/img/game_background_sky.png");
soundSystem.AddSound("/.c9/background.mp3", 1);
after_loading_state = new TitleState();
game_state = TitleState;
setInterval(gameLoop, 1000 / GAME_FPS);
}
window.addEventListener("load", onGameInit, false);
GameFramework.js
window.addEventListener("mousedown", onMouseDown, false);
window.addEventListener("mouseup", onMouseUp, false);
var GAME_FPS;
var game_state;
function onMouseDown(e)
{
if(game_state.onMouseDown != undefined)
game_state.onMouseDown(e);
// alert("x:" + inputSystem.mouseX + " y:" + inputSystem.mouseY);
}
function onMouseUp(e)
{
if(game_state.onMouseUp != undefined)
game_state.onMouseUp(e);
}
function ChangeGameState(nextGameState)
{
if(nextGameState.Init == undefined)
return;
if(nextGameState.Update == undefined)
return;
if(nextGameState.Render == undefined)
return;
game_state = nextGameState;
game_state.Init();
}
function GameUpdate()
{
timerSystem.Update();
**game_state.Update();**
debugSystem.UseDebugMode();
}
function GameRender()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
game_state.Render();
if(debugSystem.debugMode)
{
Context.fillStyle = "#ffffff";
Context.font = '15px Arial';
Context.textBaseline = "top";
Context.fillText("fps: "+ frameCounter.Lastfps, 10, 10);
}
}
function gameLoop()
{
game_state = after_loading_state;
GameUpdate();
GameRender();
frameCounter.countFrame();
}
RS_Title.js
function TitleState()
{
this.imgBackground = resourcePreLoader.GetImage("/.c9/img/title_background.png");
this.imgButtonStartOff = resourcePreLoader.GetImage("/.c9/img/title_start_off.png");
this.imgButtonStartOn = resourcePreLoader.GetImage("/.c9/img/title_start_on.png");
this.imgButtonRankingOff = resourcePreLoader.GetImage("/.c9/img/title_ranking_off.png");
this.imgButtonRankingOn = resourcePreLoader.GetImage("/.c9/img/title_ranking_on.png");
soundSystem.PlayBackgroundMusic("/.c9/background.mp3");
return this;
}
TitleState.prototype.Init = function()
{
soundSystem.PlayBackgroundMusic("/.c9/background.mp3");
};
TitleState.prototype.Render = function()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
Context.drawImage(this.imgBackground, 0, 0);
//drawing button
if(inputSystem.mouseX > 170 && inputSystem.mouseX < 170+220
&& inputSystem.mouseY > 480 && inputSystem.mouseY < 480+100)
{
Context.drawImage(this.imgButtonStartOn, 170, 480);
this.flagButtonStart = true;
}
else
{
Context.drawImage(this.imgButtonStartOff, 170, 480);
this.flagButtonStart = false;
}
if(inputSystem.mouseX > 420 && inputSystem.mouseX < 420+220
&& inputSystem.mouseY > 480 && inputSystem.mouseY < 480+100)
{
Context.drawImage(this.imgButtonRankingOn, 420, 480);
this.flagButtonRanking = true;
}
else
{
Context.drawImage(this.imgButtonRankingOff, 420, 480);
this.flagButtonRanking = false;
}
};
TitleState.prototype.Update = function()
{
};
TitleState.prototype.onMouseDown = function()
{
if(this.flagButtonStart)
ChangeGameState(new PlayGameState());
after_loading_state = PlayGameState;
game_state = PlayGameState;
if(this.flagButtonRanking)
ChangeGameState();
};
RS_PlayGame.js
function PlayGameState()
{
this.imgBackgroundSky = resourcePreLoader.GetImage("/.c9/img/game_background_sky.png");
}
PlayGameState.prototype.Init = function()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
Context.drawImage(this.imgBackgroundSky, 0, 0);
};
PlayGameState.prototype.Render = function()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
Context.drawImage(this.imgBackgroundSky, 0, 0);
};
PlayGameState.prototype.Update = function()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
Context.drawImage(this.imgBackgroundSky, 0, 0);
};
As mentioned by the others, in the onMouseDown method you are assigning after_loading_state and game_state to PlayGameState which is a function and not an object. So later on when you want to access the Update method, it simply doesn't exist, because it is defined over the object prototype and not the function. You might want to do something like this so that you also avoid instantiating (calling) PlayGameState multiple times:
game_state = new PlayGameState();
ChangeGameState(game_state);
after_loading_state = game_state;
I am a javascript function to copy paste an image from the clipboard to HTML canvas, futher i also have a function to let the user draw(highlight) on the image pasted on the canvas. However, the drawing tool function seems to override the copy paste function as it is anonymous. I need help to make these two functions operate.
this is my function to copy from clipboard.
function CLIPBOARD_CLASS(canvas_id, autoresize) {
alert("BLAH");
var _self = this;
var canvas = document.getElementById(canvas_id);
var ctx = document.getElementById(canvas_id).getContext("2d");
var ctrl_pressed = false;
var reading_dom = false;
var text_top = 15;
var pasteCatcher;
var paste_mode;
//handlers
document.addEventListener('keydown', function (e) {
_self.on_keyboard_action(e);
}, false); //firefox fix
document.addEventListener('keyup', function (e) {
_self.on_keyboardup_action(e);
}, false); //firefox fix
document.addEventListener('paste', function (e) {
_self.paste_auto(e);
}, false); //official paste handler
//constructor - prepare
this.init = function () {
//if using auto
if (window.Clipboard)
return true;
pasteCatcher = document.createElement("div");
pasteCatcher.setAttribute("id", "paste_ff");
pasteCatcher.setAttribute("contenteditable", "");
pasteCatcher.style.cssText = 'opacity:0;position:fixed;top:0px;left:0px;';
pasteCatcher.style.marginLeft = "-20px";
pasteCatcher.style.width = "10px";
document.body.appendChild(pasteCatcher);
document.getElementById('paste_ff').addEventListener('DOMSubtreeModified', function () {
if (paste_mode == 'auto' || ctrl_pressed == false)
return true;
//if paste handle failed - capture pasted object manually
if (pasteCatcher.children.length == 1) {
if (pasteCatcher.firstElementChild.src != undefined) {
//image
_self.paste_createImage(pasteCatcher.firstElementChild.src);
}
}
//register cleanup after some time.
setTimeout(function () {
pasteCatcher.innerHTML = '';
}, 20);
}, false);
}();
//default paste action
this.paste_auto = function (e) {
paste_mode = '';
pasteCatcher.innerHTML = '';
var plain_text_used = false;
if (e.clipboardData) {
var items = e.clipboardData.items;
if (items) {
paste_mode = 'auto';
//access data directly
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") !== -1) {
//image
var blob = items[i].getAsFile();
var URLObj = window.URL || window.webkitURL;
var source = URLObj.createObjectURL(blob);
this.paste_createImage(source);
}
}
e.preventDefault();
}
else {
//wait for DOMSubtreeModified event
//https://bugzilla.mozilla.org/show_bug.cgi?id=891247
}
}
};
//on keyboard press -
this.on_keyboard_action = function (event) {
k = event.keyCode;
//ctrl
if (k == 17 || event.metaKey || event.ctrlKey) {
if (ctrl_pressed == false)
ctrl_pressed = true;
}
//c
if (k == 86) {
if (document.activeElement != undefined && document.activeElement.type == 'text') {
//let user paste into some input
return false;
}
if (ctrl_pressed == true && !window.Clipboard)
pasteCatcher.focus();
}
};
//on kaybord release
this.on_keyboardup_action = function (event) {
k = event.keyCode;
//ctrl
if (k == 17 || event.metaKey || event.ctrlKey || event.key == 'Meta')
ctrl_pressed = false;
};
//draw image
this.paste_createImage = function (source) {
var pastedImage = new Image();
pastedImage.onload = function () {
if (autoresize == true) {
//resize canvas
canvas.width = pastedImage.width;
canvas.height = pastedImage.height;
}
else {
//clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
ctx.drawImage(pastedImage, 0, 0);
};
pastedImage.src = source;
};
}
This my drawing tool function
if (window.addEventListener) {
window.addEventListener('load', function () {
var canvas, context, canvaso, contexto;
// The active tool instance.
var tool;
var tool_default = 'line';
function init() {
// Find the canvas element.
canvaso = document.getElementById('my_canvas_1');
if (!canvaso) {
alert('Error: I cannot find the canvas element!');
return;
}
if (!canvaso.getContext) {
alert('Error: no canvas.getContext!');
return;
}
// Get the 2D canvas context.
contexto = canvaso.getContext('2d');
if (!contexto) {
alert('Error: failed to getContext!');
return;
}
// Add the temporary canvas.
var container = canvaso.parentNode;
canvas = document.createElement('canvas');
if (!canvas) {
alert('Error: I cannot create a new canvas element!');
return;
}
canvas.id = 'imageTemp';
canvas.width = canvaso.width;
canvas.height = canvaso.height;
container.appendChild(canvas);
context = canvas.getContext('2d');
// Get the tool select input.
var tool_select = document.getElementById('dtool');
if (!tool_select) {
alert('Error: failed to get the dtool element!');
return;
}
tool_select.addEventListener('change', ev_tool_change, false);
// Activate the default tool.
if (tools[tool_default]) {
tool = new tools[tool_default]();
tool_select.value = tool_default;
}
// Attach the mousedown, mousemove and mouseup event listeners.
canvas.addEventListener('mousedown', ev_canvas, false);
canvas.addEventListener('mousemove', ev_canvas, false);
canvas.addEventListener('mouseup', ev_canvas, false);
}
// The general-purpose event handler. This function just determines the mouse
// position relative to the canvas element.
function ev_canvas(ev) {
if (ev.layerX || ev.layerX == 0) { // Firefox
ev._x = ev.layerX;
ev._y = ev.layerY;
} else if (ev.offsetX || ev.offsetX == 0) { // Opera
ev._x = ev.offsetX;
ev._y = ev.offsetY;
}
// Call the event handler of the tool.
var func = tool[ev.type];
if (func) {
func(ev);
}
}
// The event handler for any changes made to the tool selector.
function ev_tool_change(ev) {
if (tools[this.value]) {
tool = new tools[this.value]();
}
}
// This function draws the #imageTemp canvas on top of #my_cavas_1, after which
// #imageTemp is cleared. This function is called each time when the user
// completes a drawing operation.
function img_update() {
contexto.drawImage(canvas, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);
}
// This object holds the implementation of each drawing tool.
var tools = {};
// The drawing pencil.
tools.pencil = function () {
var tool = this;
this.started = false;
// This is called when you start holding down the mouse button.
// This starts the pencil drawing.
this.mousedown = function (ev) {
context.beginPath();
context.moveTo(ev._x, ev._y);
tool.started = true;
};
// This function is called every time you move the mouse. Obviously, it only
// draws if the tool.started state is set to true (when you are holding down
// the mouse button).
this.mousemove = function (ev) {
if (tool.started) {
context.lineTo(ev._x, ev._y);
context.stroke();
}
};
// This is called when you release the mouse button.
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
img_update();
}
};
};
// The rectangle tool.
tools.rect = function () {
var tool = this;
this.started = false;
this.mousedown = function (ev) {
tool.started = true;
tool.x0 = ev._x;
tool.y0 = ev._y;
};
this.mousemove = function (ev) {
if (!tool.started) {
return;
}
var x = Math.min(ev._x, tool.x0),
y = Math.min(ev._y, tool.y0),
w = Math.abs(ev._x - tool.x0),
h = Math.abs(ev._y - tool.y0);
context.clearRect(0, 0, canvas.width, canvas.height);
if (!w || !h) {
return;
}
context.strokeRect(x, y, w, h);
};
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
img_update();
}
};
};
// The line tool.
tools.line = function () {
var tool = this;
this.started = false;
this.mousedown = function (ev) {
tool.started = true;
tool.x0 = ev._x;
tool.y0 = ev._y;
};
this.mousemove = function (ev) {
if (!tool.started) {
return;
}
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.moveTo(tool.x0, tool.y0);
context.lineTo(ev._x, ev._y);
context.stroke();
context.closePath();
};
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
img_update();
}
};
};
init();
}, false);
}
This is my HTML CANVAS TAG
<canvas id="my_canvas_1" width="300" height="300" onclick="CLIPBOARD_CLASS('my_canvas_1',true);"></canvas>
Something in this Curtains.js plug-in is preventing user text selection on my page. When I comment it out, I'm able to select text, when I put it back in, I'm not. Can someone identify it and tell me how to fix it? I'm at my wit's end.
<script>
/*
* Curtain.js - Create an unique page transitioning system
* ---
* Version: 2
* Copyright 2011, Victor Coulon (http://victorcoulon.fr)
* Released under the MIT Licence
*/
(function ( $, window, document, undefined ) {
var pluginName = 'curtain',
defaults = {
scrollSpeed: 400,
bodyHeight: 0,
linksArray: [],
mobile: false,
scrollButtons: {},
controls: null,
curtainLinks: '.curtain-links',
enableKeys: true,
easing: 'swing',
disabled: false,
nextSlide: function() {},
prevSlide: function() {}
};
// The actual plugin constructor
function Plugin( element, options ) {
var self = this;
// Public attributes
this.element = element;
this.options = $.extend( {}, defaults, options) ;
this._defaults = defaults;
this._name = pluginName;
this._ignoreHashChange = false;
this.init();
}
Plugin.prototype = {
init: function () {
var self = this;
// Cache element
this.$element = $(this.element);
this.$li = $(this.element).find('>li');
this.$liLength = this.$li.length;
self.$windowHeight = $(window).height();
self.$elDatas = {};
self.$document = $(document);
self.$window = $(window);
self.webkit = (navigator.userAgent.indexOf('Chrome') > -1 || navigator.userAgent.indexOf("Safari") > -1);
$.Android = (navigator.userAgent.match(/Android/i));
$.iPhone = ((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)));
$.iPad = ((navigator.userAgent.match(/iPad/i)));
$.iOs4 = (/OS [1-4]_[0-9_]+ like Mac OS X/i.test(navigator.userAgent));
if($.iPhone || $.iPad || $.Android || self.options.disabled){
this.options.mobile = true;
this.$li.css({position:'relative'});
this.$element.find('.fixed').css({position:'absolute'});
}
if(this.options.mobile){
this.scrollEl = this.$element;
} else if($.browser.mozilla || $.browser.msie) {
this.scrollEl = $('html');
} else {
this.scrollEl = $('body');
}
if(self.options.controls){
self.options.scrollButtons['up'] = $(self.options.controls).find('[href="#up"]');
self.options.scrollButtons['down'] = $(self.options.controls).find('[href="#down"]');
if(!$.iOs4 && ($.iPhone || $.iPad)){
self.$element.css({
position:'fixed',
top:0,
left:0,
right:0,
bottom:0,
'-webkit-overflow-scrolling':'touch',
overflow:'auto'
});
$(self.options.controls).css({position:'absolute'});
}
}
// When all image is loaded
var callbackImageLoaded = function(){
self.setDimensions();
self.$li.eq(0).addClass('current');
self.setCache();
if(!self.options.mobile){
if(self.$li.eq(1).length)
self.$li.eq(1).nextAll().addClass('hidden');
}
self.setEvents();
self.setLinks();
self.isHashIsOnList(location.hash.substring(1));
};
if(self.$element.find('img').length)
self.imageLoaded(callbackImageLoaded);
else
callbackImageLoaded();
},
// Events
scrollToPosition: function (direction){
var position = null,
self = this;
if(self.scrollEl.is(':animated')){
return false;
}
if(direction === 'up' || direction == 'down'){
// Keyboard event
var $next = (direction === 'up') ? self.$current.prev() : self.$current.next();
// Step in the current panel ?
if(self.$step){
if(!self.$current.find('.current-step').length){
self.$step.eq(0).addClass('current-step');
}
var $nextStep = (direction === 'up') ? self.$current.find('.current-step').prev('.step') : self.$current.find('.current-step').next('.step');
if($nextStep.length) {
position = (self.options.mobile) ? $nextStep.position().top + self.$elDatas[self.$current.index()]['data-position'] : $nextStep.position().top + self.$elDatas[self.$current.index()]['data-position'];
}
}
position = position || ((self.$elDatas[$next.index()] === undefined) ? null : self.$elDatas[$next.index()]['data-position']);
if(position !== null){
self.scrollEl.animate({
scrollTop: position
}, self.options.scrollSpeed, self.options.easing);
}
} else if(direction === 'top'){
self.scrollEl.animate({
scrollTop:0
}, self.options.scrollSpeed, self.options.easing);
} else if(direction === 'bottom'){
self.scrollEl.animate({
scrollTop:self.options.bodyHeight
}, self.options.scrollSpeed, self.options.easing);
} else {
var index = $("#"+direction).index(),
speed = Math.abs(self.currentIndex-index) * (this.options.scrollSpeed*4) / self.$liLength;
self.scrollEl.animate({
scrollTop:self.$elDatas[index]['data-position'] || null
}, (speed <= self.options.scrollSpeed) ? self.options.scrollSpeed : speed, this.options.easing);
}
},
scrollEvent: function() {
var self = this,
docTop = self.$document.scrollTop();
if(docTop < self.currentP && self.currentIndex > 0){
// Scroll to top
self._ignoreHashChange = true;
if(self.$current.prev().attr('id'))
self.setHash(self.$current.prev().attr('id'));
self.$current
.removeClass('current')
.css( (self.webkit) ? {'-webkit-transform': 'translateY(0px) translateZ(0)'} : {marginTop: 0} )
.nextAll().addClass('hidden').end()
.prev().addClass('current').removeClass('hidden');
self.setCache();
self.options.prevSlide();
} else if(docTop < (self.currentP + self.currentHeight)){
// Animate the current pannel during the scroll
if(self.webkit)
self.$current.css({'-webkit-transform': 'translateY('+(-(docTop-self.currentP))+'px) translateZ(0)' });
else
self.$current.css({marginTop: -(docTop-self.currentP) });
// If there is a fixed element in the current panel
if(self.$fixedLength){
var dataTop = parseInt(self.$fixed.attr('data-top'), 10);
if(docTop + self.$windowHeight >= self.currentP + self.currentHeight){
self.$fixed.css({
position: 'fixed'
});
} else {
self.$fixed.css({
position: 'absolute',
marginTop: Math.abs(docTop-self.currentP)
});
}
}
// If there is a step element in the current panel
if(self.$stepLength){
$.each(self.$step, function(i,el){
if(($(el).position().top+self.currentP) <= docTop+5 && $(el).position().top + self.currentP + $(el).height() >= docTop+5){
if(!$(el).hasClass('current-step')){
self.$step.removeClass('current-step');
$(el).addClass('current-step');
return false;
}
}
});
}
if(self.parallaxBg){
self.$current.css({
'background-position-y': docTop * self.parallaxBg
});
}
if(self.$fade.length){
self.$fade.css({
'opacity': 1-(docTop/ self.$fade.attr('data-fade'))
});
}
if(self.$slowScroll.length){
self.$slowScroll.css({
'margin-top' : (docTop / self.$slowScroll.attr('data-slow-scroll'))
});
}
} else {
// Scroll bottom
self._ignoreHashChange = true;
if(self.$current.next().attr('id'))
self.setHash(self.$current.next().attr('id'));
self.$current.removeClass('current')
.addClass('hidden')
.next('li').addClass('current').next('li').removeClass('hidden');
self.setCache();
self.options.nextSlide();
}
},
scrollMobileEvent: function() {
var self = this,
docTop = self.$element.scrollTop();
if(docTop+10 < self.currentP && self.currentIndex > 0){
// Scroll to top
self._ignoreHashChange = true;
if(self.$current.prev().attr('id'))
self.setHash(self.$current.prev().attr('id'));
self.$current.removeClass('current').prev().addClass('current');
self.setCache();
self.options.prevSlide();
} else if(docTop+10 < (self.currentP + self.currentHeight)){
// If there is a step element in the current panel
if(self.$stepLength){
$.each(self.$step, function(i,el){
if(($(el).position().top+self.currentP) <= docTop && (($(el).position().top+self.currentP) + $(el).outerHeight()) >= docTop){
if(!$(el).hasClass('current-step')){
self.$step.removeClass('current-step');
$(el).addClass('current-step');
}
}
});
}
} else {
// Scroll bottom
self._ignoreHashChange = true;
if(self.$current.next().attr('id'))
self.setHash(self.$current.next().attr('id'));
self.$current.removeClass('current').next().addClass('current');
self.setCache();
self.options.nextSlide();
}
},
// Setters
setDimensions: function(){
var self = this,
levelHeight = 0,
cover = false,
height = null;
self.$windowHeight = self.$window.height();
this.$li.each(function(index) {
var $self = $(this);
cover = $self.hasClass('cover');
if(cover){
$self.css({height: self.$windowHeight, zIndex: 999-index})
.attr('data-height',self.$windowHeight)
.attr('data-position',levelHeight);
self.$elDatas[$self.index()] = {
'data-height': parseInt(self.$windowHeight,10),
'data-position': parseInt(levelHeight, 10)
};
levelHeight += self.$windowHeight;
} else{
height = ($self.outerHeight() <= self.$windowHeight) ? self.$windowHeight : $self.outerHeight();
$self.css({minHeight: height, zIndex: 999-index})
.attr('data-height',height)
.attr('data-position',levelHeight);
self.$elDatas[$self.index()] = {
'data-height': parseInt(height, 10),
'data-position': parseInt(levelHeight, 10)
};
levelHeight += height;
}
if($self.find('.fixed').length){
var top = $self.find('.fixed').css('top');
$self.find('.fixed').attr('data-top', top);
}
});
if(!this.options.mobile)
this.setBodyHeight();
},
setEvents: function() {
var self = this;
$(window).on('resize', function(){
self.setDimensions();
});
if(self.options.mobile) {
self.$element.on('scroll', function(){
self.scrollMobileEvent();
});
} else {
self.$window.on('scroll', function(){
self.scrollEvent();
});
}
if(self.options.enableKeys) {
self.$document.on('keydown', function(e){
if(e.keyCode === 38 || e.keyCode === 37) {
self.scrollToPosition('up');
e.preventDefault();
return false;
}
if(e.keyCode === 40 || e.keyCode === 39){
self.scrollToPosition('down');
e.preventDefault();
return false;
}
// Home button
if(e.keyCode === 36){
self.scrollToPosition('top');
e.preventDefault();
return false;
}
// End button
if(e.keyCode === 35){
self.scrollToPosition('bottom');
e.preventDefault();
return false;
}
});
}
if(self.options.scrollButtons){
if(self.options.scrollButtons.up){
self.options.scrollButtons.up.on('click', function(e){
e.preventDefault();
self.scrollToPosition('up');
});
}
if(self.options.scrollButtons.down){
self.options.scrollButtons.down.on('click', function(e){
e.preventDefault();
self.scrollToPosition('down');
});
}
}
if(self.options.curtainLinks){
$(self.options.curtainLinks).on('click', function(e){
e.preventDefault();
var href = $(this).attr('href');
if(!self.isHashIsOnList(href.substring(1)) && position)
return false;
var position = self.$elDatas[$(href).index()]['data-position'] || null;
if(position){
self.scrollEl.animate({
scrollTop:position
}, self.options.scrollSpeed, self.options.easing);
}
return false;
});
}
self.$window.on("hashchange", function(event){
if(self._ignoreHashChange === false){
self.isHashIsOnList(location.hash.substring(1));
}
self._ignoreHashChange = false;
});
},
setBodyHeight: function(){
var h = 0;
for (var key in this.$elDatas) {
var obj = this.$elDatas[key];
h += obj['data-height'];
}
this.options.bodyHeight = h;
$('body').height(h);
},
setLinks: function(){
var self = this;
this.$li.each(function() {
var id = $(this).attr('id') || 0;
self.options.linksArray.push(id);
});
},
setHash: function(hash){
// "HARD FIX"
el = $('[href=#'+hash+']');
el.parent().siblings('li').removeClass('active');
el.parent().addClass('active');
if(history.pushState) {
history.pushState(null, null, '#'+hash);
}
else {
location.hash = hash;
}
},
setCache: function(){
var self = this;
self.$current = self.$element.find('.current');
self.$fixed = self.$current.find('.fixed');
self.$fixedLength = self.$fixed.length;
self.$step = self.$current.find('.step');
self.$stepLength = self.$step.length;
self.currentIndex = self.$current.index();
self.currentP = self.$elDatas[self.currentIndex]['data-position'];
self.currentHeight = self.$elDatas[self.currentIndex]['data-height'];
self.parallaxBg = self.$current.attr('data-parallax-background');
self.$fade = self.$current.find('[data-fade]');
self.$slowScroll = self.$current.find('[data-slow-scroll]');
},
// Utils
isHashIsOnList: function(hash){
var self = this;
$.each(self.options.linksArray, function(i,val){
if(val === hash){
self.scrollToPosition(hash);
return false;
}
});
},
readyElement: function(el,callback){
var interval = setInterval(function(){
if(el.length){
callback(el.length);
clearInterval(interval);
}
},60);
},
imageLoaded: function(callback){
var self = this,
elems = self.$element.find('img'),
len = elems.length,
blank = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
elems.bind('load.imgloaded',function(){
if (--len <= 0 && this.src !== blank || $(this).not(':visible')){
elems.unbind('load.imgloaded');
callback.call(elems,this);
}
}).each(function(){
if (this.complete || this.complete === undefined){
var src = this.src;
this.src = blank;
this.src = src;
}
});
}
};
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName, new Plugin( this, options ));
}
});
};
})( jQuery, window, document );
</script>
First you would have to tell us how you are trying to select text (mouse, keyboard, touchscreen, etc.)
I bet my bitcoins on keyboard (but I don't have any).
Must be one of those
self.$document.on('keydown', function(e){
...
e.preventDefault();
which don't even document which keys these numbers stand for.
It's e.preventDefault() which prevents the default browser action from being performed.
If you're in Chrome devtools, you can use
monitorEvents(window, 'key')
to make sense of these.
Of course this bit may help a bit:
keyCode: 38
keyIdentifier: "Up"
So the code could be written readably by use of keyIdentifier instead of keyCode.
I don't know how compatible that would be across browsers.
Be warned that keydown keyCode values are different from keypress values (which actually insert real characters). keydown key codes will vary between keyboard layouts and locales.
See http://unixpapa.com/js/key.html for disgust and enlightenment, but mostly disgust.