0

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>
gman
  • 100,619
  • 31
  • 269
  • 393
jeremytripp
  • 1,038
  • 1
  • 11
  • 25
  • On which device/browser? Or does it matter? – Ry- Sep 21 '13 at 20:06
  • [Github project page](https://github.com/Victa/curtain.js/) says it is no longer maintained, so you might experience more problem in a future. Did you consider using an alternative? – Pavlo Sep 21 '13 at 20:30
  • you should really narrow in on the problem area a bit so the question becomes easier to look at. more people might do so and respond, – stackunderflow Sep 21 '13 at 20:31

1 Answers1

0

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.

stackunderflow
  • 953
  • 7
  • 17