S3Slider jQuery Stop After One Rotation - javascript

I'm using an S3Slider on WordPress. I'd like it to stop after one rotation, but can't seem to figure out the setting.
The following code is used in the slider.js file. Right now it's live at http://beaconwc.com on the frontpage, would like it to show the two slides and then stop until the user refreshes the page.
(function($){
$.fn.s3Slider = function(vars) {
var element = this;
var timeOut = (vars.timeOut != undefined) ? vars.timeOut : 4000;
var current = null;
var timeOutFn = null;
var faderStat = true;
var mOver = false;
var capOpacity = vars.captionOpacity || .7;
var items = $("#" + element[0].id + "Content ." + element[0].id + "Image");
var itemsSpan = $("#" + element[0].id + "Content ." + element[0].id + "Image div");
itemsSpan.css({
'opacity': capOpacity,
'display': 'none'
});
items.each(function(i) {
$(items[i]).mouseover(function() {
mOver = true;
});
$(items[i]).mouseout(function() {
mOver = false;
fadeElement(true);
});
});
var fadeElement = function(isMouseOut) {
var thisTimeOut = (isMouseOut) ? (timeOut/2) : timeOut;
thisTimeOut = (faderStat) ? 10 : thisTimeOut;
if(items.length > 0) {
timeOutFn = setTimeout(makeSlider, thisTimeOut);
} else {
console.log("Poof..");
}
}
var makeSlider = function() {
current = (current != null) ? current : items[(items.length-1)];
var currNo = jQuery.inArray(current, items) + 1
currNo = (currNo == items.length) ? 0 : (currNo - 1);
var newMargin = $(element).width() * currNo;
if(faderStat == true) {
if(!mOver) {
$(items[currNo]).fadeIn((timeOut/6), function() {
if($(itemsSpan[currNo]).css('bottom') == 0) {
$(itemsSpan[currNo]).slideUp((timeOut/6), function() {
faderStat = false;
current = items[currNo];
if(!mOver) {
fadeElement(false);
}
});
} else {
$(itemsSpan[currNo]).slideDown((timeOut/6), function() {
faderStat = false;
current = items[currNo];
if(!mOver) {
fadeElement(false);
}
});
}
});
}
} else {
if(!mOver) {
if($(itemsSpan[currNo]).css('bottom') == 0) {
$(itemsSpan[currNo]).slideDown((timeOut/6), function() {
$(items[currNo]).fadeOut((timeOut/6), function() {
faderStat = true;
current = items[(currNo+1)];
if(!mOver) {
fadeElement(false);
}
});
});
} else {
$(itemsSpan[currNo]).slideUp((timeOut/6), function() {
$(items[currNo]).fadeOut((timeOut/6), function() {
faderStat = true;
current = items[(currNo+1)];
if(!mOver) {
fadeElement(false);
}
});
});
}
}
}
}
makeSlider();
};
})(jQuery);
Thanks!
Source
http://www.serie3.info/s3slider/

Related

i have a tempermonkey script which read data from csv file .....i want to change it based on fields on webpage

The script loads data from a CSV file. Page sometimes has five fields,
sometimes four. The script needs to adjust based on the number of fields.
forexample I need to modify this tempermonkey script
enter 4 pieces of data if there are 4 fields or enter 5 pieces of data if
there are 5 fields on the web page.
$(window).ready(function($) {
var file = GM_getResourceText('csvFile');
var csv = $.csv.toArrays(file);
var row = 0;
//var interval = setInterval(fillFormInterval, 3000);
var scope = angular.element($('body')).scope();
// scope.$on('$includeContentLoaded', function(){
// fillForm(csv[row]);
//setTimeout(fillForm(csv[row]));
//});
var interval = setInterval(fillFormInterval, 1000);
functionfillFormInterval() {
if($('#applicant-preferredCommunicationMethod').length) {
clearInterval(interval);
setTimeout(function() {
fillForm(csv[row]);
},3000);
}
}
functionfillForm(tempRow) {
var scope = angular.element($('#applicant-firstName')).scope();
if(!scope.applicant || !scope.applicant.phone1) {
return;
}
var row = new Array(5).fill(undefined);
row[1] = "NMN";
tempRow.forEach(function(data,i) {
if(data != '') {
row[i] = data;
}
});
scope.$apply(function() {
scope.applicant.firstName = row[0];
scope.applicant.middleName = row[1];
scope.applicant.lastName = row[2];
scope.applicant.dateOfBirth = row[3];
scope.applicant.dateOfBirth2 = row[3];
scope.applicant.phone1.number = row[4];
scope.applicant.preferredCommunicationMethod = "PHONE1";
scope.inherited.next();
});
//scope.applicant.countryOfBirth = "CD";
}
var interval_2 = setInterval(fillFormInterval_2, 1000);
function fillFormInterval_2() {
if($('#applicant-countryOfBirth').length) {
clearInterval(interval_2);
setTimeout(function() {
fillForm_2(csv[row]);
},3000);
}
}
functiondropDownVal(id, text) {
var value = null;
$(id).each(function() {
if(this.text.toLowerCase() == text) {
value = this.value;
value = value.split(':');
if(value.length> 1) {
value = value[1];
}else {
value = value[0];
}
}
});
return value;
}
function fillForm_2(data) {
var scope = angular.element($('#applicant-
countryOfBirth')).scope();
var country = '';
country = dropDownVal('#applicant-countryOfBirth option',
data[5].toLowerCase());
//scope.applicant.countryOfBirth = country;
var state = null;
scope.$apply(function() {
scope.applicant.countryOfBirth = country;
scope.updateStateProvince(scope.applicant.countryOfBirth);
setTimeout(function() {
if(country == "US" || country == "CD" || country == "MM") {
state = dropDownVal('#applicant-stateProvinceOfBirth
option', data[6].toLowerCase());
}
var citizen = dropDownVal('#applicant-countryOfCitizenship
option', data[7].toLowerCase());
console.log(country + " " + state + " " + citizen);
scope.applicant.countryOfCitizenship = citizen;
scope.applicant.stateProvinceOfBirth = state;
scope.$apply();
scope.inherited.next();
});
});
}
var interval_3 = setInterval(fillFormInterval_3, 1000);
function fillFormInterval_3() {
if($('.personal-questions').length) {
clearInterval(interval_3);
setTimeout(function() {
fillForm_3(csv[row]);
},3000);
}
}
function fillForm_3(data) {
e.applicant.hasMaidenPreviousName = false;
scope.applicant.hasAliasName = false;
scope.applicant.hasSameMailingResidentialAddress = true;
scope.applicant.doYouHaveAuthCode = false;
scope.applicant.viewEcNearYou = false;
scope.inherited.next();
});
}
var interval_4 = setInterval(fillFormInterval_4, 1000);
function fillFormInterval_4() {
if($('#ue-btn-US').length) {
clearInterval(interval_4);
setTimeout(function() {
fillForm_4(csv[row]);
},3000);
}
}
function fillForm_4(data) {
var scope = angular.element($('#applicant-eyeColor')).scope();
scope.$apply(function() {
scope.heightFt = parseInt(data[8].substr(0,1));
scope.heightIn = parseInt(data[8].substr(1,3));
scope.weightLb = parseInt(data[9]);
scope.applicant.hairColor = dropDownVal('#applicant-hairColor
option',
data[10].toLowerCase());
scope.applicant.eyeColor = dropDownVal('#applicant-eyeColor
option',
data[11].toLowerCase());
scope.applicant.gender = dropDownVal('#applicant-gender
option',
data[12].toLowerCase());
if(data[13].toLowerCase() == 'mixed race') {
data[13] = 'Unknown';
}else if(data[13].toLowerCase() == 'white' ||
data[13].toLowerCase() ==
'hispanic') {
data[13] = 'Caucasian/Latino';
}
scope.applicant.race = dropDownVal('#applicant-race option',
data[13].toLowerCase());
scope.inherited.next();
});
}
var interval_5 = setInterval(fillFormInterval_5, 1000);
function fillFormInterval_5() {
if($('#applicant-mailingAddress-country').length) {
clearInterval(interval_5);
setTimeout(function() {
fillForm_5(csv[row]);
},3000);
}
}
function fillForm_5(data) {
var scope = angular.element($('#applicant-mailingAddress-
country')).scope();
scope.$apply(function() {
scope.applicant.mailingAddress = {};
scope.applicant.mailingAddress.country = "US";
scope.updateStates('mailingAddress');
scope.applicant.mailingAddress.addressLine1 = data[14];
scope.applicant.mailingAddress.addressLine2 = data[15];
scope.applicant.mailingAddress.city = data[16];
setTimeout(function() {
scope.$apply(function() {
scope.applicant.mailingAddress.state = dropDownVal('#applicant-
mailingAddress-state option', data[17].toLowerCase());
scope.applicant.mailingAddress.postalCode = data[18];
scope.inherited.next();
});
});
//scope.inherited.next();
});
}
var interval_6 = setInterval(fillFormInterval_6, 1000);
function fillFormInterval_6() {
if($('#designatedRecipient-name').length) {
clearInterval(interval_6);
setTimeout(function() {
fillForm_6(csv[row]);
},3000);
}
}
function fillForm_6(data) {
var scope = angular.element($('#designatedRecipient-
name')).scope();
scope.$apply(function() {
scope.applicant.designatedRecipientName = "BIOVERIFY INC";
scope.applicant.designatedRecipientAddress = {};
scope.applicant.designatedRecipientAddress.country = "US";
scope.applicant.designatedRecipientAddress.addressLine1 = "2535
Manana
Dr.";
scope.applicant.designatedRecipientAddress.city = "Dallas";
setTimeout(function() {
scope.$apply(function() {
scope.applicant.designatedRecipientAddress.state =
dropDownVal('#applicant-designatedRecipientAddress-state
option', 'texas');
scope.applicant.designatedRecipientAddress.postalCode =
"75220";
scope.inherited.next();
});
});
scope.updateStates();
});
}
var interval_7 = setInterval(fillFormInterval_7, 1000);
function fillFormInterval_7() {
if($('#payment-nameOnCard').length) {
clearInterval(interval_7);
setTimeout(function() {
fillForm_7(csv[row]);
},3000);
}
}
function fillForm_7(data) {
var scope = angular.element($('#payment-nameOnCard')).scope();
scope.$apply(function() {
scope.applicant.payment.nameOnCard = "Brendan J Berrells";
scope.applicant.payment.cardNumber = "4246315197117185";
scope.applicant.payment.expiration = {};
scope.applicant.payment.expiration.month = 11;
scope.applicant.payment.expiration.year = "19";
scope.applicant.payment.csc = "255";
});
}
});

JavaScript - Set function to return all items based on 1 or 2 selected tags (NO jQUERY)

I have some JavaScrip that is meant to check if there are any media tags selected or industry tags selected--this is so the portfolio items can be sorted and displayed accordingly in the browser.
What I have almost works 100%, but I can't figure out how to make it so that if only a media tag is selected or if only an industry tag is selected, the portfolio items should still be sorted accordingly. Currently, you have to select a media tag AND an industry tag, but I'd like users to be able to search using just a media tag OR just an industry tag.
Here is what I want to accomplish: If only a media tag is selected, then get all portfolio pieces that are associated with that media tag. If only an industry tag is selected, get all portfolio items that are associated with that industry tag. If a media tag AND industry tag are selected at the same time, get all portfolio items that are associated with BOTH.
Vanilla JS isn't my strong point so forgive me if this is a dumb question, but this has had me stumped for hours now.
No jQuery answers, please, as this whole page's functionality is built using JavaScript.
Here is the function:
var update = function () {
closeDrawer();
// update ui to reflect tag changes
// get our list of items to display
var itemsToDisplay = [];
var currentMediaTag = controlsContainer.querySelector('.media.selected');
var currentIndustryTag = controlsContainer.querySelector('.industry.selected');
if (currentMediaTag != "" && currentMediaTag != null) {
selectedMediaFilter = currentMediaTag.innerHTML;
}
if (currentIndustryTag != "" && currentIndustryTag != null) {
selectedIndustryFilter = currentIndustryTag.innerHTML;
}
if (selectedMediaFilter == "" && selectedIndustryFilter == "") {
itemsToDisplay = portfolioItems.filter(function (item) {
return item.preferred;
});
} else {
itemsToDisplay = portfolioItems.filter(function (item) {
var mediaTags = item.media_tags,
industryTags = item.industry_tags;
if(industryTags.indexOf(selectedIndustryFilter) < 0){
return false;
}
else if(mediaTags.indexOf(selectedMediaFilter) < 0){
return false;
}
else{
return true;
}
});
}
renderItems(itemsToDisplay);
}
Not entirely sure it's necessary but just in case, here is the complete JS file that handles the portfolio page:
(function ($) {
document.addEventListener("DOMContentLoaded", function (event) {
// for portfolio interaction
var portfolioGrid = (function () {
var gridSize = undefined,
parentContainer = document.querySelector('.portfolio-item-container');
containers = parentContainer.querySelectorAll('.view'),
drawer = parentContainer.querySelector('.drawer'),
bannerContainer = drawer.querySelector('.banner-container'),
thumbsContainer = drawer.querySelector('.thumbs-container'),
descriptionContainer = drawer.querySelector('.client-description'),
clientNameContainer = drawer.querySelector('.client-name'),
controlsContainer = document.querySelector('.portfolio-controls-container'),
selectedMediaFilter = "", selectedIndustryFilter = "";
var setGridSize = function () {
var windowSize = window.innerWidth,
previousGridSize = gridSize;
if (windowSize > 1800) {
gridSize = 5;
} else if (windowSize > 900) {
gridSize = 4;
} else if (windowSize > 600 && windowSize <= 900) {
gridSize = 3;
} else {
gridSize = 2;
}
if (previousGridSize != gridSize) {
closeDrawer();
}
};
var attachResize = function () {
window.onresize = function () {
setGridSize();
};
};
var getRowClicked = function (boxNumber) {
return Math.ceil(boxNumber / gridSize);
};
var getLeftSibling = function (row) {
var cI = row * gridSize;
return containers[cI >= containers.length ? containers.length - 1 : cI];
};
var openDrawer = function () {
drawer.className = 'drawer';
scrollToBanner();
};
var scrollToBanner = function () {
var mainContainer = document.querySelector('#main-container'),
mainBounding = mainContainer.getBoundingClientRect(),
scrollY = (drawer.offsetTop - mainBounding.bottom) - 10,
currentTop = document.body.getBoundingClientRect().top;
animate(document.body, "scrollTop", "", document.body.scrollTop, scrollY, 200, true);
};
var animate = function (elem, style, unit, from, to, time, prop) {
if (!elem) return;
var start = new Date().getTime(),
timer = setInterval(function () {
var step = Math.min(1, (new Date().getTime() - start) / time);
if (prop) {
elem[style] = (from + step * (to - from)) + unit;
} else {
elem.style[style] = (from + step * (to - from)) + unit;
}
if (step == 1) clearInterval(timer);
}, 25);
elem.style[style] = from + unit;
}
var closeDrawer = function () {
drawer.className = 'drawer hidden';
};
var cleanDrawer = function () {
bannerContainer.innerHTML = "";
clientNameContainer.innerHTML = "";
descriptionContainer.innerHTML = "";
thumbsContainer.innerHTML = "";
};
var resetThumbs = function () {
Array.prototype.forEach.call(thumbsContainer.querySelectorAll('.thumb'), function (t) {
t.className = "thumb";
});
};
var handleBannerItem = function (item) {
bannerContainer.innerHTML = "";
if (item.youtube) {
var videoContainer = document.createElement('div'),
iframe = document.createElement('iframe');
videoContainer.className = "videowrapper";
iframe.className = "youtube-video";
iframe.src = "https://youtube.com/embed/" + item.youtube;
videoContainer.appendChild(iframe);
bannerContainer.appendChild(videoContainer);
} else if (item.soundcloud) {
var iframe = document.createElement('iframe');
iframe.src = item.soundcloud;
iframe.className = "soundcloud-embed";
bannerContainer.appendChild(iframe);
} else if (item.banner) {
var bannerImage = document.createElement('img');
bannerImage.src = item.banner;
bannerContainer.appendChild(bannerImage);
}
};
var attachClick = function () {
Array.prototype.forEach.call(containers, function (n, i) {
n.querySelector('a.info').addEventListener('click', function (e) {
e.preventDefault();
});
n.addEventListener('click', function (e) {
var boxNumber = i + 1,
row = getRowClicked(boxNumber);
var containerIndex = row * gridSize;
if (containerIndex >= containers.length) {
// we're inserting drawer at the end
parentContainer.appendChild(drawer);
} else {
// we're inserting drawer in the middle somewhere
var leftSiblingNode = getLeftSibling(row);
leftSiblingNode.parentNode.insertBefore(drawer, leftSiblingNode);
}
// populate
cleanDrawer();
var mediaFilterSelected = document.querySelector('.media-tags .tag-container .selected');
var selectedFilters = "";
if (mediaFilterSelected != "" && mediaFilterSelected != null) {
selectedFilters = mediaFilterSelected.innerHTML;
}
var portfolioItemName = '';
var selectedID = this.getAttribute('data-portfolio-item-id');
var data = portfolioItems.filter(function (item) {
portfolioItemName = item.name;
return item.id === selectedID;
})[0];
clientNameContainer.innerHTML = data.name;
descriptionContainer.innerHTML = data.description;
var childItems = data.child_items;
//We will group the child items by media tag and target the unique instance from each group to get the right main banner
Array.prototype.groupBy = function (prop) {
return this.reduce(function (groups, item) {
var val = item[prop];
groups[val] = groups[val] || [];
groups[val].push(item);
return groups;
}, {});
}
var byTag = childItems.groupBy('media_tags');
if (childItems.length > 0) {
handleBannerItem(childItems[0]);
var byTagValues = Object.values(byTag);
byTagValues.forEach(function (tagValue) {
for (var t = 0; t < tagValue.length; t++) {
if (tagValue[t].media_tags == selectedFilters) {
handleBannerItem(tagValue[0]);
}
}
});
childItems.forEach(function (item, i) {
var img = document.createElement('img'),
container = document.createElement('div'),
label = document.createElement('p');
container.appendChild(img);
var mediaTags = item.media_tags;
container.className = "thumb";
label.className = "childLabelInactive thumbLbl";
thumbsContainer.appendChild(container);
if (selectedFilters.length > 0 && mediaTags.length > 0) {
for (var x = 0; x < mediaTags.length; x++) {
if (mediaTags[x] == selectedFilters) {
container.className = "thumb active";
label.className = "childLabel thumbLbl";
}
}
}
else {
container.className = i == 0 ? "thumb active" : "thumb";
}
img.src = item.thumb;
if (item.media_tags != 0 && item.media_tags != null) {
childMediaTags = item.media_tags;
childMediaTags.forEach(function (cMTag) {
varLabelTxt = document.createTextNode(cMTag);
container.appendChild(label);
label.appendChild(varLabelTxt);
});
}
img.addEventListener('click', function (e) {
scrollToBanner();
resetThumbs();
handleBannerItem(item);
container.className = "thumb active";
});
});
}
openDrawer();
});
});
};
var preloadImages = function () {
portfolioItems.forEach(function (item) {
var childItems = item.child_items;
childItems.forEach(function (child) {
(new Image()).src = child.banner;
(new Image()).src = child.thumb;
});
});
};
//////////////////////////////////// UPDATE FUNCTION /////////////////////////////////////
var update = function () {
closeDrawer();
// update ui to reflect tag changes
// get our list of items to display
var itemsToDisplay = [];
var currentMediaTag = controlsContainer.querySelector('.media.selected');
var currentIndustryTag = controlsContainer.querySelector('.industry.selected');
if (currentMediaTag != "" && currentMediaTag != null) {
selectedMediaFilter = currentMediaTag.innerHTML;
}
if (currentIndustryTag != "" && currentIndustryTag != null) {
selectedIndustryFilter = currentIndustryTag.innerHTML;
}
if (selectedMediaFilter == "" && selectedIndustryFilter == "") {
itemsToDisplay = portfolioItems.filter(function (item) {
return item.preferred;
});
} else {
itemsToDisplay = portfolioItems.filter(function (item) {
var mediaTags = item.media_tags,
industryTags = item.industry_tags;
if (industryTags.indexOf(selectedIndustryFilter) < 0) {
return false;
}
else if (mediaTags.indexOf(selectedMediaFilter) < 0) {
return false;
}
else {
return true;
}
});
}
renderItems(itemsToDisplay);
}
//////////////////////////////////// RENDERITEMS FUNCTION /////////////////////////////////////
var renderItems = function (items) {
var children = parentContainer.querySelectorAll('.view');
Array.prototype.forEach.call(children, function (child) {
// remove all event listeners then remove child
parentContainer.removeChild(child);
});
items.forEach(function (item) {
var container = document.createElement('div'),
thumb = document.createElement('img'),
mask = document.createElement('div'),
title = document.createElement('h6'),
excerpt = document.createElement('p'),
link = document.createElement('a');
container.className = "view view-tenth";
container.setAttribute('data-portfolio-item-id', item.id);
thumb.src = item.thumb;
mask.className = "mask";
title.innerHTML = item.name;
excerpt.innerHTML = item.excerpt;
link.href = "#";
link.className = "info";
link.innerHTML = "View Work";
container.appendChild(thumb);
container.appendChild(mask);
mask.appendChild(title);
mask.appendChild(excerpt);
mask.appendChild(link);
parentContainer.insertBefore(container, drawer);
});
containers = parentContainer.querySelectorAll('.view');
attachClick();
};
var filterHandler = function (linkNode, tagType) {
var prevSelection = document.querySelector("." + tagType + '.selected');
if (prevSelection != "" && prevSelection != null) {
prevSelection.className = tagType + ' tag';
}
linkNode.className = tagType + ' tag selected';
update();
};
var clearFilters = function (nodeList, filterType) {
Array.prototype.forEach.call(nodeList, function (node) {
node.className = filterType + " tag";
console.log("Clear filters function called");
});
}
var attachFilters = function () {
var mediaFilters = controlsContainer.querySelectorAll('.tag.media'),
industryFilters = controlsContainer.querySelectorAll('.tag.industry'),
filterToggle = controlsContainer.querySelectorAll('.filter-toggle');
// resets
controlsContainer.querySelector('.media-tags .reset')
.addEventListener('click',
function (e) {
e.preventDefault();
selectedMediaFilter = "";
clearFilters(controlsContainer.querySelectorAll('.media-tags a.tag'), "media");
update();
}
);
controlsContainer.querySelector('.industry-tags .reset')
.addEventListener('click',
function (e) {
e.preventDefault();
selectedIndustryFilter = "";
clearFilters(controlsContainer.querySelectorAll('.industry-tags a.tag'), "industry");
update();
}
);
Array.prototype.forEach.call(filterToggle, function (toggle) {
toggle.addEventListener('click', function (e) {
if (controlsContainer.className.indexOf('open') < 0) {
controlsContainer.className += ' open';
} else {
controlsContainer.className = controlsContainer.className.replace('open', '');
}
});
});
//Attaches a click event to each media tag "button"
Array.prototype.forEach.call(mediaFilters, function (filter) {
filter.addEventListener('click', function (e) {
e.preventDefault();
// var selectedMediaFilter = controlsContainer.querySelector('.media.selected');
//console.log("Media tag: " +this.innerHTML); *THIS WORKS*
filterHandler(this, "media");
});
});
Array.prototype.forEach.call(industryFilters, function (filter) {
filter.addEventListener('click', function (e) {
e.preventDefault();
// var selectedIndustryFilter = this.querySelector('.industry.selected');
// console.log("Industry tag: " +this.innerHTML); *THIS WORKS*
filterHandler(this, "industry");
});
});
};
return {
init: function () {
setGridSize();
attachResize();
attachClick();
preloadImages();
// portfolio page
if (controlsContainer) {
attachFilters();
}
}
};
})();
portfolioGrid.init();
});
}());
$ = jQuery.noConflict();
if(industryTags.indexOf(selectedIndustryFilter) < 0){
return false;
}
else if(mediaTags.indexOf(selectedMediaFilter) < 0){
return false;
}
That part is giving you headaches. Whenever no industry tag or media tag is selected this will exit the function.
Change to:
if(industryTags.indexOf(selectedIndustryFilter) < 0 && mediaTags.indexOf(selectedMediaFilter) < 0){
return false;
}
Now it will test if at least one tag is selected. If so then render items.
I made a change just to experiment with an idea, and this setup works:
if((selectedIndustryFilter !="" && industryTags.indexOf(selectedIndustryFilter) < 0) || (selectedMediaFilter !="" && mediaTags.indexOf(selectedMediaFilter) < 0)){
return false;
}
return true;
Not sure if it's the best solution ever but it seems to work and I'm not going to complain.

Cannot fix Syntax error: Unexpected token '<'

I have been trying to fix a piece of javascript code but am not having any luck. The syntax looks correct but I keep getting an unexpected token '<' syntax error.
Please do not mark this question as a duplicate since I could not find the answer to my problem on this site.
Javascript:
// Function to get elements by class name for DOM fragment and tag name
function getElementsByClassName(objElement, strTagName, strClassName)
{
var objCollection = objElement.getElementsByTagName(strTagName);
var arReturn = [];
var strClass, arClass, iClass, iCounter;
for(iCounter=0; iCounter<objCollection.length; iCounter++)
{
strClass = objCollection[iCounter].className;
if (strClass)
{
arClass = strClass.split(' ');
for (iClass=0; iClass<arClass.length; iClass++)
{
if (arClass[iClass] == strClassName)
{
arReturn.push(objCollection[iCounter]);
break;
}
}
}
}
objCollection = null;
return (arReturn);
}
var drag = {
objCurrent : null,
arTargets : ['Fav', 'Tol', 'Rej'],
initialise : function(objNode)
{
// Add event handlers
objNode.onmousedown = drag.start;
objNode.onclick = function() {this.focus();};
objNode.onkeydown = drag.keyboardDragDrop;
document.body.onclick = drag.removePopup;
},
keyboardDragDrop : function(objEvent)
{
objEvent = objEvent || window.event;
drag.objCurrent = this;
var arChoices = ['Favourite artists', 'Tolerable artists', 'Rejected artists'];
var iKey = objEvent.keyCode;
var objItem = drag.objCurrent;
var strExisting = objItem.parentNode.getAttribute('id');
var objMenu, objChoice, iCounter;
if (iKey == 32)
{
document.onkeydown = function(){return objEvent.keyCode==38 || objEvent.keyCode==40 ? false : true;};
// Set ARIA properties
drag.objCurrent.setAttribute('aria-grabbed', 'true');
drag.objCurrent.setAttribute('aria-owns', 'popup');
// Build context menu
objMenu = document.createElement('ul');
objMenu.setAttribute('id', 'popup');
objMenu.setAttribute('role', 'menu');
for (iCounter=0; iCounter<arChoices.length; iCounter++)
{
if (drag.arTargets[iCounter] != strExisting)
{
objChoice = document.createElement('li');
objChoice.appendChild(document.createTextNode(arChoices[iCounter]));
objChoice.tabIndex = -1;
objChoice.setAttribute('role', 'menuitem');
objChoice.onmousedown = function() {drag.dropObject(this.firstChild.data.substr(0, 3));};
objChoice.onkeydown = drag.handleContext;
objChoice.onmouseover = function() {if (this.className.indexOf('hover') < 0) {this.className += ' hover';} };
objChoice.onmouseout = function() {this.className = this.className.replace(/\s*hover/, ''); };
objMenu.appendChild(objChoice);
}
}
objItem.appendChild(objMenu);
objMenu.firstChild.focus();
objMenu.firstChild.className = 'focus';
drag.identifyTargets(true);
}
},
removePopup : function()
{
document.onkeydown = null;
var objContext = document.getElementById('popup');
if (objContext)
{
objContext.parentNode.removeChild(objContext);
}
},
handleContext : function(objEvent)
{
objEvent = objEvent || window.event;
var objItem = objEvent.target || objEvent.srcElement;
var iKey = objEvent.keyCode;
var objFocus, objList, strTarget, iCounter;
// Cancel default behaviour
if (objEvent.stopPropagation)
{
objEvent.stopPropagation();
}
else if (objEvent.cancelBubble)
{
objEvent.cancelBubble = true;
}
if (objEvent.preventDefault)
{
objEvent.preventDefault();
}
else if (objEvent.returnValue)
{
objEvent.returnValue = false;
}
switch (iKey)
{
case 38 : // Down arrow
objFocus = objItem.nextSibling;
if (!objFocus)
{
objFocus = objItem.previousSibling;
}
objItem.className = '';
objFocus.focus();
objFocus.className = 'focus';
break;
case 40 : // Up arrow
objFocus = objItem.previousSibling;
if (!objFocus)
{
objFocus = objItem.nextSibling;
}
objItem.className = '';
objFocus.focus();
objFocus.className = 'focus';
break;
case 13 : // Enter
strTarget = objItem.firstChild.data.substr(0, 3);
drag.dropObject(strTarget);
break;
case 27 : // Escape
case 9 : // Tab
drag.objCurrent.removeAttribute('aria-owns');
drag.objCurrent.removeChild(objItem.parentNode);
drag.objCurrent.focus();
for (iCounter=0; iCounter<drag.arTargets.length; iCounter++)
{
objList = document.getElementById(drag.arTargets[iCounter]);
drag.objCurrent.setAttribute('aria-grabbed', 'false');
objList.removeAttribute('aria-dropeffect');
objList.className = '';
}
break;
}
},
start : function(objEvent)
{
objEvent = objEvent || window.event;
drag.removePopup();
// Initialise properties
drag.objCurrent = this;
drag.objCurrent.lastX = objEvent.clientX;
drag.objCurrent.lastY = objEvent.clientY;
drag.objCurrent.style.zIndex = '2';
drag.objCurrent.setAttribute('aria-grabbed', 'true');
document.onmousemove = drag.drag;
document.onmouseup = drag.end;
drag.identifyTargets(true);
return false;
},
drag : function(objEvent)
{
objEvent = objEvent || window.event;
// Calculate new position
var iCurrentY = objEvent.clientY;
var iCurrentX = objEvent.clientX;
var iYPos = parseInt(drag.objCurrent.style.top, 10);
var iXPos = parseInt(drag.objCurrent.style.left, 10);
var iNewX, iNewY;
iNewX = iXPos + iCurrentX - drag.objCurrent.lastX;
iNewY = iYPos + iCurrentY - drag.objCurrent.lastY;
drag.objCurrent.style.left = iNewX + 'px';
drag.objCurrent.style.top = iNewY + 'px';
drag.objCurrent.lastX = iCurrentX;
drag.objCurrent.lastY = iCurrentY;
return false;
},
calculatePosition : function (objElement, strOffset)
{
var iOffset = 0;
// Get offset position in relation to parent nodes
if (objElement.offsetParent)
{
do
{
iOffset += objElement[strOffset];
objElement = objElement.offsetParent;
} while (objElement);
}
return iOffset;
},
identifyTargets : function (bHighlight)
{
var strExisting = drag.objCurrent.parentNode.getAttribute('id');
var objList, iCounter;
// Highlight the targets for the current drag item
for (iCounter=0; iCounter<drag.arTargets.length; iCounter++)
{
objList = document.getElementById(drag.arTargets[iCounter]);
if (bHighlight && drag.arTargets[iCounter] != strExisting)
{
objList.className = 'highlight';
objList.setAttribute('aria-dropeffect', 'move');
}
else
{
objList.className = '';
objList.removeAttribute('aria-dropeffect');
}
}
},
getTarget : function()
{
var strExisting = drag.objCurrent.parentNode.getAttribute('id');
var iCurrentLeft = drag.calculatePosition(drag.objCurrent, 'offsetLeft');
var iCurrentTop = drag.calculatePosition(drag.objCurrent, 'offsetTop');
var iTolerance = 40;
var objList, iLeft, iRight, iTop, iBottom, iCounter;
for (iCounter=0; iCounter<drag.arTargets.length; iCounter++)
{
if (drag.arTargets[iCounter] != strExisting)
{
// Get position of the list
objList = document.getElementById(drag.arTargets[iCounter]);
iLeft = drag.calculatePosition(objList, 'offsetLeft') - iTolerance;
iRight = iLeft + objList.offsetWidth + iTolerance;
iTop = drag.calculatePosition(objList, 'offsetTop') - iTolerance;
iBottom = iTop + objList.offsetHeight + iTolerance;
// Determine if current object is over the target
if (iCurrentLeft > iLeft && iCurrentLeft < iRight && iCurrentTop > iTop && iCurrentTop < iBottom)
{
return drag.arTargets[iCounter];
}
}
}
// Current object is not over a target
return '';
},
dropObject : function(strTarget)
{
var objClone, objOriginal, objTarget, objEmpty, objBands, objItem;
drag.removePopup();
if (strTarget.length > 0)
{
// Copy node to new target
objOriginal = drag.objCurrent.parentNode;
objClone = drag.objCurrent.cloneNode(true);
// Remove previous attributes
objClone.removeAttribute('style');
objClone.className = objClone.className.replace(/\s*focused/, '');
objClone.className = objClone.className.replace(/\s*hover/, '');
// Add focus indicators
objClone.onfocus = function() {this.className += ' focused'; };
objClone.onblur = function() {this.className = this.className.replace(/\s*focused/, '');};
objClone.onmouseover = function() {if (this.className.indexOf('hover') < 0) {this.className += ' hover';} };
objClone.onmouseout = function() {this.className = this.className.replace(/\s*hover/, ''); };
objTarget = document.getElementById(strTarget);
objOriginal.removeChild(drag.objCurrent);
objTarget.appendChild(objClone);
drag.objCurrent = objClone;
drag.initialise(objClone);
// Remove empty node if there are artists in list
objEmpty = getElementsByClassName(objTarget, 'li', 'empty');
if (objEmpty[0])
{
objTarget.removeChild(objEmpty[0]);
}
// Add an empty node if there are no artists in list
objBands = objOriginal.getElementsByTagName('li');
if (objBands.length === 0)
{
objItem = document.createElement('li');
objItem.appendChild(document.createTextNode('None'));
objItem.className = 'empty';
objOriginal.appendChild(objItem);
}
}
// Reset properties
drag.objCurrent.style.left = '0px';
drag.objCurrent.style.top = '0px';
drag.objCurrent.style.zIndex = 'auto';
drag.objCurrent.setAttribute('aria-grabbed', 'false');
drag.objCurrent.removeAttribute('aria-owns');
drag.identifyTargets(false);
},
end : function()
{
var strTarget = drag.getTarget();
drag.dropObject(strTarget);
document.onmousemove = null;
document.onmouseup = null;
drag.objCurrent = null;
}
};
function init ()
{
var objItems = getElementsByClassName(document, 'li', 'draggable');
var objItem, iCounter;
for (iCounter=0; iCounter<objItems.length; iCounter++)
{
// Set initial values so can be moved
objItems[iCounter].style.top = '0px';
objItems[iCounter].style.left = '0px';
// Put the list items into the keyboard tab order
objItems[iCounter].tabIndex = 0;
// Set ARIA attributes for artists
objItems[iCounter].setAttribute('aria-grabbed', 'false');
objItems[iCounter].setAttribute('aria-haspopup', 'true');
objItems[iCounter].setAttribute('role', 'listitem');
// Provide a focus indicator
objItems[iCounter].onfocus = function() {this.className += ' focused'; };
objItems[iCounter].onblur = function() {this.className = this.className.replace(/\s*focused/, '');};
objItems[iCounter].onmouseover = function() {if (this.className.indexOf('hover') < 0) {this.className += ' hover';} };
objItems[iCounter].onmouseout = function() {this.className = this.className.replace(/\s*hover/, ''); };
drag.initialise(objItems[iCounter]);
}
// Set ARIA properties on the drag and drop list, and set role of this region to application
for (iCounter=0; iCounter<drag.arTargets.length; iCounter++)
{
objItem = document.getElementById(drag.arTargets[iCounter]);
objItem.setAttribute('aria-labelledby', drag.arTargets[iCounter] + 'h');
objItem.setAttribute('role', 'list');
}
objItem = document.getElementById('dragdrop');
objItem.setAttribute('role', 'application');
objItems = null;
}
window.onload = init;
This type of problem usually occurs when issuing an AJAX request which expects JSON or JavaScript as a response but it receives HTML in stead.
When expecting JSON or JavaScript the text of the response must be "eval"-uated by a JavaScript parser. If HTML code is received and evaluated as JSON or JavaScript, the presence of a lower than < or a greater than > symbol will cause errors.

JQuery: How to refactor JQuery interaction with interface?

The question is very simple but also a bit theoretical.
Let's imagine you have a long JQuery script which modifies and animate the graphics of the web site. It's objective is to handle the UI. The UI has to be responsive so the real need for this JQuery is to mix some state of visualization (sportlist visible / not visible) with some need due to Responsive UI.
Thinking from an MVC / AngularJS point of view. How should a programmer handle that?
How to refactor JS / JQuery code to implement separation of concerns described by MVC / AngularJS?
I provide an example of JQuery code to speak over something concrete.
$.noConflict();
jQuery(document).ready(function ($) {
/*variables*/
var sliderMenuVisible = false;
/*dom object variables*/
var $document = $(document);
var $window = $(window);
var $pageHost = $(".page-host");
var $sportsList = $("#sports-list");
var $mainBody = $("#mainBody");
var $toTopButtonContainer = $('#to-top-button-container');
/*eventHandlers*/
var displayError = function (form, error) {
$("#error").html(error).removeClass("hidden");
};
var calculatePageLayout = function () {
$pageHost.height($(window).height());
if ($window.width() > 697) {
$sportsList.removeAttr("style");
$mainBody
.removeAttr("style")
.unbind('touchmove')
.removeClass('stop-scroll');
if ($(".betslip-access-button")[0]) {
$(".betslip-access-button").fadeIn(500);
}
sliderMenuVisible = false;
} else {
$(".betslip-access-button").fadeOut(500);
}
};
var formSubmitHandler = function (e) {
var $form = $(this);
// We check if jQuery.validator exists on the form
if (!$form.valid || $form.valid()) {
$.post($form.attr("action"), $form.serializeArray())
.done(function (json) {
json = json || {};
// In case of success, we redirect to the provided URL or the same page.
if (json.success) {
window.location = json.redirect || location.href;
} else if (json.error) {
displayError($form, json.error);
}
})
.error(function () {
displayError($form, "Login service not available, please try again later.");
});
}
// Prevent the normal behavior since we opened the dialog
e.preventDefault();
};
//preliminary functions//
$window.on("load", calculatePageLayout);
$window.on("resize", calculatePageLayout);
//$(document).on("click","a",function (event) {
// event.preventDefault();
// window.location = $(this).attr("href");
//});
/*evet listeners*/
$("#login-form").submit(formSubmitHandler);
$("section.navigation").on("shown hidden", ".collapse", function (e) {
var $icon = $(this).parent().children("button").children("i").first();
if (!$icon.hasClass("icon-spin")) {
if (e.type === "shown") {
$icon.removeClass("icon-caret-right").addClass("icon-caret-down");
} else {
$icon.removeClass("icon-caret-down").addClass("icon-caret-right");
}
}
toggleBackToTopButton();
e.stopPropagation();
});
$(".collapse[data-src]").on("show", function () {
var $this = $(this);
if (!$this.data("loaded")) {
var $icon = $this.parent().children("button").children("i").first();
$icon.removeClass("icon-caret-right icon-caret-down").addClass("icon-refresh icon-spin");
console.log("added class - " + $icon.parent().html());
$this.load($this.data("src"), function () {
$this.data("loaded", true);
$icon.removeClass("icon-refresh icon-spin icon-caret-right").addClass("icon-caret-down");
console.log("removed class - " + $icon.parent().html());
});
}
toggleBackToTopButton();
});
$("#sports-list-button").on("click", function (e)
{
if (!sliderMenuVisible)
{
$sportsList.animate({ left: "0" }, 500);
$mainBody.animate({ left: "85%" }, 500)
.bind('touchmove', function (e2) { e2.preventDefault(); })
.addClass('stop-scroll');
$(".betslip-access-button").fadeOut(500);
sliderMenuVisible = true;
}
else
{
$sportsList.animate({ left: "-85%" }, 500).removeAttr("style");
$mainBody.animate({ left: "0" }, 500).removeAttr("style")
.unbind('touchmove').removeClass('stop-scroll');
$(".betslip-access-button").fadeIn(500);
sliderMenuVisible = false;
}
e.preventDefault();
});
$mainBody.on("click", function (e) {
if (sliderMenuVisible) {
$sportsList.animate({ left: "-85%" }, 500).removeAttr("style");
$mainBody.animate({ left: "0" }, 500)
.removeAttr("style")
.unbind('touchmove')
.removeClass('stop-scroll');
$(".betslip-access-button").fadeIn(500);
sliderMenuVisible = false;
e.stopPropagation();
e.preventDefault();
}
});
$document.on("click", "div.event-info", function () {
if (!sliderMenuVisible) {
var url = $(this).data("url");
if (url) {
window.location = url;
}
}
});
function whatDecimalSeparator() {
var n = 1.1;
n = n.toLocaleString().substring(1, 2);
return n;
}
function getValue(textBox) {
var value = textBox.val();
var separator = whatDecimalSeparator();
var old = separator == "," ? "." : ",";
var converted = parseFloat(value.replace(old, separator));
return converted;
}
$(document).on("click", "a.selection", function (e) {
if (sliderMenuVisible) {
return;
}
var $this = $(this);
var isLive = $this.data("live");
var url = "/" + _language + "/BetSlip/Add/" + $this.data("selection") + "?odds=" + $this.data("odds") + "&live=" + isLive;
var urlHoveringBtn = "/" + _language + '/BetSlip/AddHoveringButton/' + $this.data("selection") + "?odds=" + $this.data("odds") + "&live=" + isLive;
$.ajax(urlHoveringBtn).done(function (dataBtn) {
if ($(".betslip-access-button").length == 0 && dataBtn.length > 0) {
$("body").append(dataBtn);
}
});
$.ajax(url).done(function (data) {
if ($(".betslip-access").length == 0 && data.length > 0) {
$(".navbar").append(data);
$pageHost.addClass("betslipLinkInHeader");
var placeBetText = $("#live-betslip-popup").data("placebettext");
var continueText = $("#live-betslip-popup").data("continuetext");
var useQuickBetLive = $("#live-betslip-popup").data("usequickbetlive").toLowerCase() == "true";
var useQuickBetPrematch = $("#live-betslip-popup").data("usequickbetprematch").toLowerCase() == "true";
if ((isLive && useQuickBetLive) || (!isLive && useQuickBetPrematch)) {
var dialog = $("#live-betslip-popup").dialog({
modal: true,
dialogClass: "fixed-dialog"
});
dialog.dialog("option", "buttons", [
{
text: placeBetText,
click: function () {
var placeBetUrl = "/" + _language + "/BetSlip/QuickBet?amount=" + getValue($("#live-betslip-popup-amount")) + "&live=" + $this.data("live");
window.location = placeBetUrl;
}
},
{
text: continueText,
click: function () {
dialog.dialog("close");
}
}
]);
}
}
if (data.length > 0) {
$this.addClass("in-betslip");
}
});
e.preventDefault();
});
$(document).on("click", "a.selection.in-betslip", function (e) {
if (sliderMenuVisible) {
return;
}
var $this = $(this);
var isLive = $this.data("live");
var url = "/" + _language + "/BetSlip/RemoveAjax/" + $this.data("selection") + "?odds=" + $this.data("odds") + "&live=" + isLive;
$.ajax(url).done(function (data) {
if (data.success) {
$this.removeClass("in-betslip");
if (data.selections == 0) {
$(".betslip-access").remove();
$(".betslip-access-button").remove();
$(".page-host").removeClass("betslipLinkInHeader");
}
}
});
e.preventDefault();
});
$("section.betslip .total-stake button.live-betslip-popup-plusminus").click(function (e) {
if (sliderMenuVisible) {
return;
}
e.preventDefault();
var action = $(this).data("action");
var amount = parseFloat($(this).data("amount"));
if (!isNumeric(amount)) amount = 1;
var totalStake = $("#live-betslip-popup-amount").val();
if (isNumeric(totalStake)) {
totalStake = parseFloat(totalStake);
} else {
totalStake = 0;
}
if (action == "decrease") {
if (totalStake < 1.21) {
totalStake = 1.21;
}
totalStake -= amount;
} else if (action == "increase") {
totalStake += amount;
}
$("#live-betslip-popup-amount").val(totalStake);
});
toggleBackToTopButton();
function toggleBackToTopButton() {
isScrollable() ? $toTopButtonContainer.show() : $toTopButtonContainer.hide();
}
$("#to-top-button").on("click", function () { $("#mainBody").animate({ scrollTop: 0 }); });
function isScrollable() {
return $("section.navigation").height() > $(window).height() + 93;
}
var isNumeric = function (string) {
return !isNaN(string) && isFinite(string) && string != "";
};
function enableQuickBet() {
}
});
My steps in such cases are:
First of all write (at least) one controller
Replace all eventhandler with ng-directives (ng-click most of all)
Pull the view state out of the controller with ng-style and ng-class. In most of all cases ng-show and ng-hide will be sufficed
If there is code that will be used more than once, consider writing a directive.
And code that has nothing todo with the view state - put the code in a service
write unit tests (i guess there is no one until now:) )

JavaScript Preventing User Text Selection

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.

Categories

Resources