curving text using button jquery - javascript

i would like to know how i can make more designs using http://circletype.labwire.ca/#fitText i was succesful on making one but that is about it it only makes a circle i cant make more designs something is wrong with my code can someone please help? also how can i make wedge text and "wiggle" text one last thing i would also like to know how to make spiral text if some one knows any of these it would be a great help
$("#fs").change(function() {
//alert($(this).val());
$('.changeMe').css("font-family", $(this).val());
});
$("#size").change(function() {
$('.changeMe').css("font-size", $(this).val() + "px");
});
$("#demo1").click(function(){
$('.changeMe').circleType("fitText:true", $(this).attr('radius: 180'));
});
/**
* Arctext.js
* A jQuery plugin for curved text
* http://www.codrops.com
*
* Copyright 2011, Pedro Botelho / Codrops
* Free to use under the MIT license.
*
* Date: Mon Jan 23 2012
*/
(function( $, undefined ) {
/*!
* FitText.js 1.0
*
* Copyright 2011, Dave Rupert http://daverupert.com
* Released under the WTFPL license
* http://sam.zoy.org/wtfpl/
*
* Date: Thu May 05 14:23:00 2011 -0600
*/
$.fn.fitText = function( kompressor, options ) {
var settings = {
'minFontSize' : Number.NEGATIVE_INFINITY,
'maxFontSize' : Number.POSITIVE_INFINITY
};
return this.each(function() {
var $this = $(this); // store the object
var compressor = kompressor || 1; // set the compressor
if ( options ) {
$.extend( settings, options );
}
// Resizer() resizes items based on the object width divided by the compressor * 10
var resizer = function () {
$this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)));
};
// Call once to set.
resizer();
// Call on resize. Opera debounces their resize by default.
$(window).resize(resizer);
});
};
/*
* Lettering plugin
*
* changed injector function:
* add for empty chars.
*/
function injector(t, splitter, klass, after) {
var a = t.text().split(splitter), inject = '', emptyclass;
if (a.length) {
$(a).each(function(i, item) {
emptyclass = '';
if(item === ' ') {
emptyclass = ' empty';
item=' ';
}
inject += '<span class="'+klass+(i+1)+emptyclass+'">'+item+'</span>'+after;
});
t.empty().append(inject);
}
}
var methods = {
init : function() {
return this.each(function() {
injector($(this), '', 'char', '');
});
},
words : function() {
return this.each(function() {
injector($(this), ' ', 'word', ' ');
});
},
lines : function() {
return this.each(function() {
var r = "eefec303079ad17405c889e092e105b0";
// Because it's hard to split a <br/> tag consistently across browsers,
// (*ahem* IE *ahem*), we replaces all <br/> instances with an md5 hash
// (of the word "split"). If you're trying to use this plugin on that
// md5 hash string, it will fail because you're being ridiculous.
injector($(this).children("br").replaceWith(r).end(), r, 'line', '');
});
}
};
$.fn.lettering = function( method ) {
// Method calling logic
if ( method && methods[method] ) {
return methods[ method ].apply( this, [].slice.call( arguments, 1 ));
} else if ( method === 'letters' || ! method ) {
return methods.init.apply( this, [].slice.call( arguments, 0 ) ); // always pass an array
}
$.error( 'Method ' + method + ' does not exist on jQuery.lettering' );
return this;
};
/*
* Arctext object.
*/
$.Arctext = function( options, element ) {
this.$el = $( element );
this._init( options );
};
$.Arctext.defaults = {
radius : 0, // the minimum value allowed is half of the word length. if set to -1, the word will be straight.
dir : 1, // 1: curve is down, -1: curve is up.
rotate : true, // if true each letter will be rotated.
fitText : false // if you wanna try out the fitText plugin (http://fittextjs.com/) set this to true. Don't forget the wrapper should be fluid.
};
$.Arctext.prototype = {
_init : function( options ) {
this.options = $.extend( true, {}, $.Arctext.defaults, options );
// apply the lettering plugin.
this._applyLettering();
this.$el.data( 'arctext', true );
// calculate values
this._calc();
// apply transformation.
this._rotateWord();
// load the events
this._loadEvents();
},
_applyLettering : function() {
this.$el.lettering();
if( this.options.fitText )
this.$el.fitText();
this.$letters = this.$el.find('span').css('display', 'inline-block');
},
_calc : function() {
if( this.options.radius === -1 )
return false;
// calculate word / arc sizes & distances.
this._calcBase();
// get final values for each letter.
this._calcLetters();
},
_calcBase : function() {
// total word width (sum of letters widths)
this.dtWord = 0;
var _self = this;
this.$letters.each( function(i) {
var $letter = $(this),
letterWidth = $letter.outerWidth( true );
_self.dtWord += letterWidth;
// save the center point of each letter:
$letter.data( 'center', _self.dtWord - letterWidth / 2 );
});
// the middle point of the word.
var centerWord = this.dtWord / 2;
// check radius : the minimum value allowed is half of the word length.
if( this.options.radius < centerWord )
this.options.radius = centerWord;
// total arc segment length, where the letters will be placed.
this.dtArcBase = this.dtWord;
// calculate the arc (length) that goes from the beginning of the first letter (x=0) to the end of the last letter (x=this.dtWord).
// first lets calculate the angle for the triangle with base = this.dtArcBase and the other two sides = radius.
var angle = 2 * Math.asin( this.dtArcBase / ( 2 * this.options.radius ) );
// given the formula: L(ength) = R(adius) x A(ngle), we calculate our arc length.
this.dtArc = this.options.radius * angle;
},
_calcLetters : function() {
var _self = this,
iteratorX = 0;
this.$letters.each( function(i) {
var $letter = $(this),
// calculate each letter's semi arc given the percentage of each letter on the original word.
dtArcLetter = ( $letter.outerWidth( true ) / _self.dtWord ) * _self.dtArc,
// angle for the dtArcLetter given our radius.
beta = dtArcLetter / _self.options.radius,
// distance from the middle point of the semi arc's chord to the center of the circle.
// this is going to be the place where the letter will be positioned.
h = _self.options.radius * ( Math.cos( beta / 2 ) ),
// angle formed by the x-axis and the left most point of the chord.
alpha = Math.acos( ( _self.dtWord / 2 - iteratorX ) / _self.options.radius ),
// angle formed by the x-axis and the right most point of the chord.
theta = alpha + beta / 2,
// distances of the sides of the triangle formed by h and the orthogonal to the x-axis.
x = Math.cos( theta ) * h,
y = Math.sin( theta ) * h,
// the value for the coordinate x of the middle point of the chord.
xpos = iteratorX + Math.abs( _self.dtWord / 2 - x - iteratorX ),
// finally, calculate how much to translate each letter, given its center point.
// also calculate the angle to rotate the letter accordingly.
xval = 0| xpos - $letter.data( 'center' ),
yval = 0| _self.options.radius - y,
angle = ( _self.options.rotate ) ? 0| -Math.asin( x / _self.options.radius ) * ( 180 / Math.PI ) : 0;
// the iteratorX will be positioned on the second point of each semi arc
iteratorX = 2 * xpos - iteratorX;
// save these values
$letter.data({
x : xval,
y : ( _self.options.dir === 1 ) ? yval : -yval,
a : ( _self.options.dir === 1 ) ? angle : -angle
});
});
},
_rotateWord : function( animation ) {
if( !this.$el.data('arctext') ) return false;
var _self = this;
this.$letters.each( function(i) {
var $letter = $(this),
transformation = ( _self.options.radius === -1 ) ? 'none' : 'translateX(' + $letter.data('x') + 'px) translateY(' + $letter.data('y') + 'px) rotate(' + $letter.data('a') + 'deg)',
transition = ( animation ) ? 'all ' + ( animation.speed || 0 ) + 'ms ' + ( animation.easing || 'linear' ) : 'none';
$letter.css({
'-webkit-transition' : transition,
'-moz-transition' : transition,
'-o-transition' : transition,
'-ms-transition' : transition,
'transition' : transition
})
.css({
'-webkit-transform' : transformation,
'-moz-transform' : transformation,
'-o-transform' : transformation,
'-ms-transform' : transformation,
'transform' : transformation
});
});
},
_loadEvents : function() {
if( this.options.fitText ) {
var _self = this;
$(window).on( 'resize.arctext', function() {
_self._calc();
// apply transformation.
_self._rotateWord();
});
}
},
set : function( opts ) {
if( !opts.radius &&
!opts.dir &&
opts.rotate === 'undefined' ) {
return false;
}
this.options.radius = opts.radius || this.options.radius;
this.options.dir = opts.dir || this.options.dir;
if( opts.rotate !== undefined ) {
this.options.rotate = opts.rotate;
}
this._calc();
this._rotateWord( opts.animation );
},
destroy : function() {
this.options.radius = -1;
this._rotateWord();
this.$letters.removeData('x y a center');
this.$el.removeData('arctext');
$(window).off('.arctext');
}
};
var logError = function( message ) {
if ( this.console ) {
console.error( message );
}
};
$.fn.arctext = function( options ) {
if ( typeof options === 'string' ) {
var args = Array.prototype.slice.call( arguments, 1 );
this.each(function() {
var instance = $.data( this, 'arctext' );
if ( !instance ) {
logError( "cannot call methods on arctext prior to initialization; " +
"attempted to call method '" + options + "'" );
return;
}
if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
logError( "no such method '" + options + "' for arctext instance" );
return;
}
instance[ options ].apply( instance, args );
});
}
else {
this.each(function() {
var instance = $.data( this, 'arctext' );
if ( !instance ) {
$.data( this, 'arctext', new $.Arctext( options, this ) );
}
});
}
return this;
};
})( jQuery );
/*
* CircleType 0.36
* Peter Hrynkow
* Copyright 2014, Licensed GPL & MIT
*
*/
$.fn.circleType = function(options) {
var self = this,
settings = {
dir: 1,
position: 'relative',
};
if (typeof($.fn.lettering) !== 'function') {
console.log('Lettering.js is required');
return;
}
return this.each(function () {
if (options) {
$.extend(settings, options);
}
var elem = this,
delta = (180 / Math.PI),
fs = parseInt($(elem).css('font-size'), 10),
ch = parseInt($(elem).css('line-height'), 10) || fs,
txt = elem.innerHTML.replace(/^\s+|\s+$/g, '').replace(/\s/g, ' '),
letters,
center;
elem.innerHTML = txt
$(elem).lettering();
elem.style.position = settings.position;
letters = elem.getElementsByTagName('span');
center = Math.floor(letters.length / 2)
var layout = function () {
var tw = 0,
i,
offset = 0,
minRadius,
origin,
innerRadius,
l, style, r, transform;
for (i = 0; i < letters.length; i++) {
tw += letters[i].offsetWidth;
}
minRadius = (tw / Math.PI) / 2 + ch;
if (settings.fluid && !settings.fitText) {
settings.radius = Math.max(elem.offsetWidth / 2, minRadius);
}
else if (!settings.radius) {
settings.radius = minRadius;
}
if (settings.dir === -1) {
origin = 'center ' + (-settings.radius + ch) / fs + 'em';
} else {
origin = 'center ' + settings.radius / fs + 'em';
}
innerRadius = settings.radius - ch;
for (i = 0; i < letters.length; i++) {
l = letters[i];
offset += l.offsetWidth / 2 / innerRadius * delta;
l.rot = offset;
offset += l.offsetWidth / 2 / innerRadius * delta;
}
for (i = 0; i < letters.length; i++) {
l = letters[i]
style = l.style
r = (-offset * settings.dir / 2) + l.rot * settings.dir
transform = 'rotate(' + r + 'deg)';
style.position = 'absolute';
style.left = '50%';
style.marginLeft = -(l.offsetWidth / 2) / fs + 'em';
style.webkitTransform = transform;
style.MozTransform = transform;
style.OTransform = transform;
style.msTransform = transform;
style.transform = transform;
style.webkitTransformOrigin = origin;
style.MozTransformOrigin = origin;
style.OTransformOrigin = origin;
style.msTransformOrigin = origin;
style.transformOrigin = origin;
if(settings.dir === -1) {
style.bottom = 0;
}
}
if (settings.fitText) {
if (typeof($.fn.fitText) !== 'function') {
console.log('FitText.js is required when using the fitText option');
} else {
$(elem).fitText();
$(window).resize(function () {
updateHeight();
});
}
}
updateHeight();
if (typeof settings.callback === 'function') {
// Execute our callback with the element we transformed as `this`
settings.callback.apply(elem);
}
};
var getBounds = function (elem) {
var docElem = document.documentElement,
box = elem.getBoundingClientRect();
return {
top: box.top + window.pageYOffset - docElem.clientTop,
left: box.left + window.pageXOffset - docElem.clientLeft,
height: box.height
};
};
var updateHeight = function () {
var mid = getBounds(letters[center]),
first = getBounds(letters[0]),
h;
if (mid.top < first.top) {
h = first.top - mid.top + first.height;
} else {
h = mid.top - first.top + first.height;
}
elem.style.height = h + 'px';
}
if (settings.fluid && !settings.fitText) {
$(window).resize(function () {
layout();
});
}
if (document.readyState !== "complete") {
elem.style.visibility = 'hidden';
$(window).load(function () {
elem.style.visibility = 'visible';
layout();
});
} else {
layout();
}
});
};
<form id="myform">
<select id="fs">
<option value="Arial">Arial</option>
<option value="Verdana ">Verdana </option>
<option value="Impact ">Impact </option>
<option value="Comic Sans MS">Comic Sans MS</option>
</select>
<select id="size">
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="14">14</option>
<option value="16">16</option>
<option value="18">18</option>
<option value="20">20</option>
<option value="22">22</option>
<option value="24">24</option>
<option value="26">26</option>
<option value="28">28</option>
<option value="30">30</option>
<option value="32">32</option>
<option value="34">34</option>
<option value="36">36</option>
</select>
<div id="demo1">Here is some text I would like to see in a different shape.</div>
</form>
<br/>
<div id="container" class="changeMe">
Hello World 1234567890<div id="float">
</div>
</div>
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script><script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script><link rel="stylesheet"
href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<link rel="stylesheet"
href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script src="https://circletype.labwire.ca/js/circletype.js"></script>
<script src="https://tympanus.net/Development/Arctext/js/jquery.arctext.js"></script>

My guess is that your problem is with this code:
$("#demo1").click(function(){
$('.changeMe').circleType("fitText:true", $(this).attr('radius: 180'));
});
You do not have a proper div matching this code. I'll come back to this in a minute but first you should know that usually one does not go in and edit a library directly. My suggestion is that you play with your code inside of its own separate <script> tags.
So maybe after you finish loading your libraries:
<script>
$("#fs").change(function() {
//alert($(this).val());
$('.changeMe').css("font-family", $(this).val());
});
$("#size").change(function() {
$('.changeMe').css("font-size", $(this).val() + "px");
});
$("#demo1").click(function(){
$('.changeMe').circleType("fitText:true", $(this).attr('radius: 180'));
});
</script>
Then you just need to modify your HTML so that you have a demo1 div that is not a button:
<div id="demo1">Here is some text I would like to see in a different shape.</div>
This code probably likes to run against regular old HTML text and not a button.
Hope this helps!
UPDATE: I got rid of your redundant libraries and simplified your code. This example should work when placed between the <body> tags in an HTML document. Click each line to see it in action. I also moved your stylesheets into the document <head> tag where they belong.
<div id="demo1">Here is some text I would like to see in a different shape.</div>
<div id="demo2">Here is some text I would like to see in a different shape.</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<script src="http://circletype.labwire.ca/js/circletype.js"></script>
<script src="http://tympanus.net/Development/Arctext/js/jquery.arctext.js"></script>
<script>
$("#demo1").click(function(){
$('#demo1').circleType({radius:384});
});
$("#demo2").click(function(){
$('#demo2').circleType({radius:384, dir:-1});
});
</script>

Related

Ruby on Rails 6 custom JavaScript file Uncaught ReferenceError: Rellax is not defined

Descriptions of issue
It supposes to add Parallax effect on .rellax elements according to https://github.com/dixonandmoe/rellax
If you are familiar with Ruby on Rails 6 and Webpacker, would you please explain why rails can't read rellax.js properly and what can I do to make it work? Thank you!
Terminal
$ rails s
=> Booting Puma
=> Rails 6.0.3.2 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.5 (ruby 2.6.6-p146), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop
Started GET "/" for ::1 at 2020-07-15 18:34:48 -0700
(1.0ms) SELECT sqlite_version(*)
Processing by WelcomeController#index as HTML
Rendering welcome/index.html.erb within layouts/application
[Webpacker] Everything's up-to-date. Nothing to do
Rendered welcome/index.html.erb within layouts/application (Duration: 4.8ms | Allocations: 2428)
[Webpacker] Everything's up-to-date. Nothing to do
Completed 200 OK in 47ms (Views: 39.7ms | ActiveRecord: 0.0ms | Allocations: 13263)
index.html.erb
<h1>Welcome#index</h1>
<p>Find me in app/views/welcome/index.html.erb</p>
<h4>data-rellax-speed = default</h4>
<section>
<div class="col">
<br>With Percentage (0.5) <br><br>
<div id="21" class="container"><div class="block">#1<span class="rellax" data-rellax-percentage="0.5">#1</span></div></div>
<div id="22" class="container"><div class="block">#2<span class="rellax" data-rellax-percentage="0.5">#2</span></div></div>
<div id="23" class="container"><div class="block">#3<span class="rellax" data-rellax-percentage="0.5">#3</span></div></div>
<div id="24" class="container"><div class="block">#4<span class="rellax" data-rellax-percentage="0.5" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#4</span></div></div>
<div id="25" class="container"><div class="block">#5<span class="rellax" data-rellax-percentage="0.5" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#5</span></div></div>
<div id="26" class="container"><div class="block">#6<span class="rellax" data-rellax-percentage="0.5" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#6</span></div></div>
</div>
<div class="col">
<br>Without Percentage <br><br>
<div id="21" class="container"><div class="block">#1<span class="rellax" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#1</span></div></div>
<div id="22" class="container"><div class="block">#2<span class="rellax" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#2</span></div></div>
<div id="23" class="container"><div class="block">#3<span class="rellax" style="transition: transform 10s cubic-bezier(0,1,.5,1);">#3</span></div></div>
<div id="24" class="container"><div class="block">#4<span class="rellax">#4</span></div></div>
<div id="25" class="container"><div class="block">#5<span class="rellax">#5</span></div></div>
<div id="26" class="container"><div class="block">#6<span class="rellax">#6</span></div></div>
</div>
</section>
<!-- Scripts -->
<%= javascript_pack_tag 'rellax' %>
<script>
var rellax = new Rellax('.rellax');
</script>
app/javascript/packs/rellax.js
// ------------------------------------------
// Rellax.js
// Buttery smooth parallax library
// Copyright (c) 2016 Moe Amaya (#moeamaya)
// MIT license
//
// Thanks to Paraxify.js and Jaime Cabllero
// for parallax concepts
// ------------------------------------------
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.Rellax = factory();
}
}(typeof window !== "undefined" ? window : global, function () {
var Rellax = function(el, options){
"use strict";
var self = Object.create(Rellax.prototype);
var posY = 0;
var screenY = 0;
var posX = 0;
var screenX = 0;
var blocks = [];
var pause = true;
// check what requestAnimationFrame to use, and if
// it's not supported, use the onscroll event
var loop = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback){ return setTimeout(callback, 1000 / 60); };
// store the id for later use
var loopId = null;
// Test via a getter in the options object to see if the passive property is accessed
var supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
}
});
window.addEventListener("testPassive", null, opts);
window.removeEventListener("testPassive", null, opts);
} catch (e) {}
// check what cancelAnimation method to use
var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
// check which transform property to use
var transformProp = window.transformProp || (function(){
var testEl = document.createElement('div');
if (testEl.style.transform === null) {
var vendors = ['Webkit', 'Moz', 'ms'];
for (var vendor in vendors) {
if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
return vendors[vendor] + 'Transform';
}
}
}
return 'transform';
})();
// Default Settings
self.options = {
speed: -2,
verticalSpeed: null,
horizontalSpeed: null,
breakpoints: [576, 768, 1201],
center: false,
wrapper: null,
relativeToWrapper: false,
round: true,
vertical: true,
horizontal: false,
verticalScrollAxis: "y",
horizontalScrollAxis: "x",
callback: function() {},
};
// User defined options (might have more in the future)
if (options){
Object.keys(options).forEach(function(key){
self.options[key] = options[key];
});
}
function validateCustomBreakpoints () {
if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
var isAscending = true;
var isNumerical = true;
var lastVal;
self.options.breakpoints.forEach(function (i) {
if (typeof i !== 'number') isNumerical = false;
if (lastVal !== null) {
if (i < lastVal) isAscending = false;
}
lastVal = i;
});
if (isAscending && isNumerical) return;
}
// revert defaults if set incorrectly
self.options.breakpoints = [576, 768, 1201];
console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
}
if (options && options.breakpoints) {
validateCustomBreakpoints();
}
// By default, rellax class
if (!el) {
el = '.rellax';
}
// check if el is a className or a node
var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
// Now query selector
if (elements.length > 0) {
self.elems = elements;
}
// The elements don't exist
else {
console.warn("Rellax: The elements you're trying to select don't exist.");
return;
}
// Has a wrapper and it exists
if (self.options.wrapper) {
if (!self.options.wrapper.nodeType) {
var wrapper = document.querySelector(self.options.wrapper);
if (wrapper) {
self.options.wrapper = wrapper;
} else {
console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
return;
}
}
}
// set a placeholder for the current breakpoint
var currentBreakpoint;
// helper to determine current breakpoint
var getCurrentBreakpoint = function (w) {
var bp = self.options.breakpoints;
if (w < bp[0]) return 'xs';
if (w >= bp[0] && w < bp[1]) return 'sm';
if (w >= bp[1] && w < bp[2]) return 'md';
return 'lg';
};
// Get and cache initial position of all elements
var cacheBlocks = function() {
for (var i = 0; i < self.elems.length; i++){
var block = createBlock(self.elems[i]);
blocks.push(block);
}
};
// Let's kick this script off
// Build array for cached element values
var init = function() {
for (var i = 0; i < blocks.length; i++){
self.elems[i].style.cssText = blocks[i].style;
}
blocks = [];
screenY = window.innerHeight;
screenX = window.innerWidth;
currentBreakpoint = getCurrentBreakpoint(screenX);
setPosition();
cacheBlocks();
animate();
// If paused, unpause and set listener for window resizing events
if (pause) {
window.addEventListener('resize', init);
pause = false;
// Start the loop
update();
}
};
// We want to cache the parallax blocks'
// values: base, top, height, speed
// el: is dom object, return: el cache values
var createBlock = function(el) {
var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
var dataSpeed = el.getAttribute( 'data-rellax-speed' );
var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
var dataMin = el.getAttribute( 'data-rellax-min' );
var dataMax = el.getAttribute( 'data-rellax-max' );
var dataMinX = el.getAttribute('data-rellax-min-x');
var dataMaxX = el.getAttribute('data-rellax-max-x');
var dataMinY = el.getAttribute('data-rellax-min-y');
var dataMaxY = el.getAttribute('data-rellax-max-y');
var mapBreakpoints;
var breakpoints = true;
if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
breakpoints = false;
} else {
mapBreakpoints = {
'xs': dataXsSpeed,
'sm': dataMobileSpeed,
'md': dataTabletSpeed,
'lg': dataDesktopSpeed
};
}
// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
// ensures elements are positioned based on HTML layout.
//
// If the element has the percentage attribute, the posY and posX needs to be
// the current scroll position's value, so that the elements are still positioned based on HTML layout
var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
if (self.options.relativeToWrapper) {
var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
}
var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
var posX = self.options.horizontal ? ( dataPercentage || self.options.center ? self.options.wrapper ? self.options.wrapper.scrollLeft : (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft) : 0 ) : 0;
var blockTop = posY + el.getBoundingClientRect().top;
var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
var blockLeft = posX + el.getBoundingClientRect().left;
var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
// apparently parallax equation everyone uses
var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
// Optional individual block speed as data attr, otherwise global speed
var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
// Optional individual block movement axis direction as data attr, otherwise gobal movement direction
var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
// ~~Store non-translate3d transforms~~
// Store inline styles and extract transforms
var style = el.style.cssText;
var transform = '';
// Check if there's an inline styled transform
var searchResult = /transform\s*:/i.exec(style);
if (searchResult) {
// Get the index of the transform
var index = searchResult.index;
// Trim the style to the transform point and get the following semi-colon index
var trimmedStyle = style.slice(index);
var delimiter = trimmedStyle.indexOf(';');
// Remove "transform" string and save the attribute
if (delimiter) {
transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
} else {
transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
}
}
return {
baseX: bases.x,
baseY: bases.y,
top: blockTop,
left: blockLeft,
height: blockHeight,
width: blockWidth,
speed: speed,
verticalSpeed: verticalSpeed,
horizontalSpeed: horizontalSpeed,
verticalScrollAxis: verticalScrollAxis,
horizontalScrollAxis: horizontalScrollAxis,
style: style,
transform: transform,
zindex: dataZindex,
min: dataMin,
max: dataMax,
minX: dataMinX,
maxX: dataMaxX,
minY: dataMinY,
maxY: dataMaxY
};
};
// set scroll position (posY, posX)
// side effect method is not ideal, but okay for now
// returns true if the scroll changed, false if nothing happened
var setPosition = function() {
var oldY = posY;
var oldX = posX;
posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
// If option relativeToWrapper is true, use relative wrapper value instead.
if (self.options.relativeToWrapper) {
var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
posY = scrollPosY - self.options.wrapper.offsetTop;
}
if (oldY != posY && self.options.vertical) {
// scroll changed, return true
return true;
}
if (oldX != posX && self.options.horizontal) {
// scroll changed, return true
return true;
}
// scroll did not change
return false;
};
// Ahh a pure function, gets new transform value
// based on scrollPosition and speed
// Allow for decimal pixel values
var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
var result = {};
var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
return result;
};
// Remove event listeners and loop again
var deferredUpdate = function() {
window.removeEventListener('resize', deferredUpdate);
window.removeEventListener('orientationchange', deferredUpdate);
(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
// loop again
loopId = loop(update);
};
// Loop
var update = function() {
if (setPosition() && pause === false) {
animate();
// loop again
loopId = loop(update);
} else {
loopId = null;
// Don't animate until we get a position updating event
window.addEventListener('resize', deferredUpdate);
window.addEventListener('orientationchange', deferredUpdate);
(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
}
};
// Transform3d on parallax element
var animate = function() {
var positions;
for (var i = 0; i < self.elems.length; i++){
// Determine relevant movement directions
var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
// Subtracting initialize value, so element stays in same spot as HTML
positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
var positionY = positions.y - blocks[i].baseY;
var positionX = positions.x - blocks[i].baseX;
// The next two "if" blocks go like this:
// Check if a limit is defined (first "min", then "max");
// Check if we need to change the Y or the X
// (Currently working only if just one of the axes is enabled)
// Then, check if the new position is inside the allowed limit
// If so, use new position. If not, set position to limit.
// Check if a min limit is defined
if (blocks[i].min !== null) {
if (self.options.vertical && !self.options.horizontal) {
positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
}
if (self.options.horizontal && !self.options.vertical) {
positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
}
}
// Check if directional min limits are defined
if (blocks[i].minY != null) {
positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
}
if (blocks[i].minX != null) {
positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
}
// Check if a max limit is defined
if (blocks[i].max !== null) {
if (self.options.vertical && !self.options.horizontal) {
positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
}
if (self.options.horizontal && !self.options.vertical) {
positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
}
}
// Check if directional max limits are defined
if (blocks[i].maxY != null) {
positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
}
if (blocks[i].maxX != null) {
positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
}
var zindex = blocks[i].zindex;
// Move that element
// (Set the new translation and append initial inline transforms.)
var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
self.elems[i].style[transformProp] = translate;
}
self.options.callback(positions);
};
self.destroy = function() {
for (var i = 0; i < self.elems.length; i++){
self.elems[i].style.cssText = blocks[i].style;
}
// Remove resize event listener if not pause, and pause
if (!pause) {
window.removeEventListener('resize', init);
pause = true;
}
// Clear the animation loop to prevent possible memory leak
clearLoop(loopId);
loopId = null;
};
// Init
init();
// Allow to recalculate the initial values whenever we want
self.refresh = init;
return self;
};
return Rellax;
}));
Error: Uncaught ReferenceError: Rellax is not defined
I just realized that the package you are trying to import is intended to be included as an AMD or as a node module, without entering in much detail what does that mean is that you should include your module either by using
import Rellax from 'rellax' or let Rellax = require('rellax'), the thing is that by using this kind of import, your packages are not included in the Window objcet, which is the main object where all the global modules and variables are attached, so if you try to access Rellax from outside of the scope where rellax is imported, you are not going to be able to access that object, getting the error message you mentioned:
Rellax is not defined
Because is actually not defined in that scope.
TLDR;
So in order to fix the issue, you have to include the library and use that library in the same scope, you can achieve that by creating a new js file within your pack directory for example:
parallax_init.js
import Rellax from 'rellax'
let rellax = new Rellax('.rellax');
And then include it in your html template using <%= javascript_pack_tag 'parallax_init' %>
Note:
As you are now using webpacker to handle the js dependencies, you have to use yarn to install the packages as webpacker works with yarn.
You can get more information about the JS scope stuff in the AMD documentation: https://requirejs.org/docs/whyamd.html and in the webpack documentation: https://webpack.js.org/concepts/module-federation/
I also recommend you to read the webpacker documentation, which has a bit more information than the rails guide for the moment(Until the rails guide gets updates): https://github.com/rails/webpacker#usage
You can have two approachs to achieve your goal. Install the library or add manually the js files.
If you want to install the library, use yarn (not npm) for that. yarn add rellax. Then just import it in application.js by doing: import 'rellax'; This file is located in app/javascript/packs.
If you want to add the files manually, put these js files in a folder called components or plugins inside app/javascript. Then import all js files in application.js. Having done this correctly, all js files will be available in your views.
It's highly recommended that you read the Rails Guide: The Asset Pipeline to understand how to deal with any kind of assets in rails applications.

How to check with d3.js if element is in viewpoint (in visible area)

I'm drawing large number of elements and in many situations majority of elements are outside of view point.
I'd like to avoid processing expensive rotation transformations on hidden elements.
Here's an example:
https://blockchaingraph.org/#ipfs-QmfXtMeUdjWBPQHUNKvF3nkYR57aZz7qarW5qikEUYWJvw
Many elements in this graph are hidden (try to zoom out to see). But currently I have to render each element on every tick and it's getting painfully slow.
Here's my code:
function transformLinks(svgLinks, nodeRadius, arrowSize) {
if (svgLinks) {
var link = svgLinks.selectAll('.link').filter(needRedraw);
//console.log("total:", svgLinks.selectAll('.link').size(), ',needRedraw:', link.size());
transformLinksLines(link);
transformLinksTexts(link.selectAll('.text'));
transformLinksOutlines(link, nodeRadius, arrowSize);
transformLinksOverlays(link.selectAll('.overlay'));
link.each(function (n) {
n.source.lx = n.source.x;
n.source.ly = n.source.y;
n.target.lx = n.target.x;
n.target.ly = n.target.y;
});
}
}
function needRedraw(link) {
if (!link.source) {
link = link.parentNode;
}
return nodeMoved(link.source) || nodeMoved(link.target);
}
var minDistToRedraw = 0.8;
function nodeMoved(n) {
return utils.isNumber(n.x) && utils.isNumber(n.y)
&& !(utils.isNumber(n.lx) && Math.abs(n.x - n.lx) <= minDistToRedraw && Math.abs(n.y - n.ly) <= minDistToRedraw);
}
I'd like to extend needRedraw() function to check for visibility. For now the function just checks if either linked node moved significantly enough.
Since I didn't find any out of box solution I had to get into those coordinate conversion stuff.
First, I created function that translates external container coordinates into SVG internal clients coordianate system - containerToSVG()
Then applied it on .getBoundingClientRect(); to get visible area in SVG coordinate space.
Then in the filter checking if both nodes outsize of visible area - do not redraw link.
There are possible situations when both nodes are outsize the area, but link can still cross the area. But it's not a big concern as long as user don't see link detachments.
Here's the code:
function transformLinks(svgLinks, nodeRadius, arrowSize) {
if (svgLinks) {
var containerRect = container.node().getBoundingClientRect();
var p = containerToSVG(-nodeRadius, -nodeRadius);
var r = containerToSVG(containerRect.width + nodeRadius, containerRect.height + nodeRadius);
svgVisibleRect = {left: p.x, top: p.y, right: r.x, bottom: r.y};
minDistToRedraw = (svgVisibleRect.right - svgVisibleRect.left) / (containerRect.width + nodeRadius * 2);
var link = svgLinks.selectAll('.link').filter(needRedraw);
transformLinksLines(link);
transformLinksTexts(link.selectAll('.text'));
transformLinksOutlines(link, nodeRadius, arrowSize);
transformLinksOverlays(link.selectAll('.overlay'));
link.each(function (n) {
updateLastCoord(n.source);
updateLastCoord(n.target);
});
}
}
function needRedraw(link) {
if (!nodeMoved(link.source) && !nodeMoved(link.target)) {
return false;
}
return isVisible(link.source) || isVisible(link.target);
}
function nodeMoved(n) {
return utils.isNumber(n.x) && utils.isNumber(n.y) &&
!(utils.isNumber(n.lx) && Math.abs(n.x - n.lx) <= minDistToRedraw && Math.abs(n.y - n.ly) <= minDistToRedraw);
}
function isVisible(n) {
var result = n.x > svgVisibleRect.left && n.x < svgVisibleRect.right &&
n.y > svgVisibleRect.top && n.y < svgVisibleRect.bottom;
return result;
}
function updateLastCoord(n) {
n.lx = n.x;
n.ly = n.y;
}
function containerToSVG(containerX, containerY) {
var svgPount = svgNode.createSVGPoint();
svgPount.x = containerX;
svgPount.y = containerY;
return svgPount.matrixTransform(document.getElementById("links-svg").getScreenCTM().inverse());
}
function transformLinksLines(link) {
link.attr('transform', function (d) {
var angle = rotation(d.source, d.target);
return 'translate(' + d.source.x + ', ' + d.source.y + ') rotate(' + angle + ')';
});
}

Script Re-sizing Webpage

I am currently using a Shooting Star script I found online to randomize shooting stars across the webpage. Whenever a shooting star goes out of the visible webpage, scroll bars appear and re-size the entire page for a moment. This happens quite frequently. Is there a way I can just have the shooting star delete itself once it hits the edge of the webpage, or maybe have it so that the webpage isn't affected by the shooting stars? Here's the website where I got the script from: http://codepen.io/manufosela/pen/Gymih
Here's the code:
<html>
<head>
<title>Shooting star Example</title>
<meta charset="utf-8">
<meta name="author" content="#manufosela">
</head>
<body class="stars">
<h1>SHOOTING STARS...</h1>
<div id="ShootingStarParams"></div>
<script type="text/javascript" src="http://codeorigin.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="ShootingStarClass.js"></script>
<script type="text/javascript">
$( document ).ready( function(){
var shootingStarObj = new ShootingStar( "body" );
shootingStarObj.launch();
});
</script>
</body>
</html>
body { color:#FFF; height:600px; width:99%; height:95%; color:#FFF; }
.stars {
z-index: 0; position: absolute; /* width: 420em; height: 70em; */
background-image: url( http://www.14denoviembre.es/img/hori.png ), url( http://www.14denoviembre.es/img/stars_5.png ); background-repeat: repeat-x,repeat-x repeat-y;
transform:translate3D(0em, 0em, 0); animation: stars 21s ease; transform-style: preserve-3d;
}
(function(){
/**
author: #manufosela
2013/08/27 copyleft 2013
ShootingStar class Main Methods:
launch: launch shooting stars every N seconds received by param. 10 seconds by default.
launchStar: launch a shooting star. Received options object by param with:
- dir (direction between 0 and 1)
- life (between 100 and 400)
- beamSize (between 400 and 700)
- velocity (between 2 and 10)
**/
ShootingStar = function( id ) {
this.n = 0;
this.m = 0;
this.defaultOptions = { velocity:8, starSize:10, life:300, beamSize:400, dir:-1 };
this.options = {};
id = ( typeof id != "undefined" )?id:"";
this.capa = ( $( id ).lenght > 0 )?"body":id;
this.wW = $( this.capa ).innerWidth();
this.hW = $( this.capa ).innerHeight();
};
ShootingStar.prototype.addBeamPart = function( x, y ) {
this.n++;
var name = this.getRandom( 100, 1 );
$( "#star"+name ).remove();
$( this.capa ).append( "<div id='star"+name+"'></div>" );
$( "#star"+name ).append( "<div id='haz"+this.n+"' class='haz' style='position:absolute; color:#FF0; width:10px; height:10px; font-weight:bold; font-size:"+this.options.starSize+"px'>·</div>" );
if ( this.n > 1 ) $( "#haz" + ( this.n - 1 ) ).css( { color:"rgba(255,255,255,0.5)" } );
$( "#haz" + this.n ).css( { top: y + this.n, left: x + ( this.n * this.options.dir ) } );
}
ShootingStar.prototype.delTrozoHaz = function() {
this.m++;
$( "#haz" + this.m ).animate( {opacity:0}, 75 );
if ( this.m >= this.options.beamSize ) { $( "#ShootingStarParams" ).fadeOut( "slow" ); }
}
ShootingStar.prototype.getRandom = function( max, min ) {
return Math.floor( Math.random() * (max - min + 1)) + min;
}
ShootingStar.prototype.toType = function ( obj ) {
if ( typeof obj === "undefined" ) { return "undefined"; /* consider: typeof null === object */ }
if ( obj === null ) { return "null"; }
var type = Object.prototype.toString.call( obj ).match( /^\[object\s(.*)\]$/ )[1] || '';
switch ( type ) {
case 'Number': if ( isNaN( obj ) ) { return "nan"; } else { return "number"; }
case 'String': case 'Boolean': case 'Array': case 'Date': case 'RegExp': case 'Function': return type.toLowerCase();
}
if ( typeof obj === "object" ) { return "object"; }
return undefined;
}
ShootingStar.prototype.launchStar = function( options ) {
if ( this.toType( options ) != "object" ) { options = {}; }
this.options = $.extend( {}, this.defaultOptions, options );
this.n=0;
this.m=0;
var i=0, l=this.options.beamSize,
x=this.getRandom( this.wW - this.options.beamSize - 100, 100 ), y=this.getRandom( this.hW - this.options.beamSize - 100, 100 ),
self = this;
for( ; i<l; i++ ) { setTimeout( function(){ self.addBeamPart( x, y ); }, self.options.life + ( i * self.options.velocity ) ); }
for( i=0; i<l; i++ ) { setTimeout( function(){ self.delTrozoHaz() }, self.options.beamSize + ( i * self.options.velocity ) ); }
$( "#ShootingStarParams" ).html( "Launching shooting star. PARAMS: wW: " + this.wW + " - hW: " + this.hW + " - life: " + this.options.life + " - beamSize: " + this.options.beamSize + " - velocity: " + this.options.velocity );
$( "#ShootingStarParams" ).fadeIn( "slow" );
}
ShootingStar.prototype.launch = function( everyTime ) {
if ( this.toType( everyTime ) != "number" ) { everyTime = 10; }
everyTime = everyTime * 1000;
this.launchStar();
var self = this;
setInterval( function() {
var options = {
dir: ( self.getRandom( 1, 0 ))?1:-1,
life: self.getRandom( 400, 100 ),
beamSize: self.getRandom( 700, 400 ),
velocity: self.getRandom( 10, 4 )
}
self.launchStar( options );
}, everyTime );
}
})();
body {
overflow: hidden;
}
This prevents scrollbars from appearing when content of an element goes beyond its dimensions.

Extending Touch EventListener to Additional DOM Element

I used a Codrops article/experiment to create an interactive environment for a local group to use at their conferences. The problem with this is the default interaction is not very intuitive. The template used Flickity.js and what seems like classie.js to create this sliding interface I am having trouble with.
The page can be found here:
www.eyeconic.tv/ky-ffa/
Issue: The only way to activate the view-full is by clicking on the html element:
<h2 class=".stack-title">
// After the stack is active you should be able to activate the full view by clicking on the first .stack-item used to create the thumbnail below it. This entire div should be clickable. Users are touching everywhere all over the screen and not actually clicking the title for the desired action. I hope this makes sense.
In other words you should be able to click the stack-title and the image below the title of each stack to pull the stack into the full view mode on the screen. Then click the x or anywhere else on the screen to close the full view.
The following is located in main.js and the reference I found to create the events I am referring to.
//
function initEvents() {
stacks.forEach(function(stack) {
var titleEl = stack.querySelector('.stack-title');
// expand/close the stack
titleEl.addEventListener('click', function(ev) {
ev.preventDefault();
if( classie.has(stack, 'is-selected') ) { // current stack
if( classie.has(bodyEl, 'view-full') ) { // stack is opened
var closeStack = function() {
classie.remove(bodyEl, 'move-items');
onEndTransition(slider, function() {
classie.remove(bodyEl, 'view-full');
bodyEl.style.height = '';
flkty.bindDrag();
flkty.options.accessibility = true;
canMoveHeroImage = true;
});
};
// if the user scrolled down, let's first scroll all up before closing the stack.
var scrolled = scrollY();
if( scrolled > 0 ) {
smooth_scroll_to(isFirefox ? docElem : bodyEl || docElem, 0, 500).then(function() {
closeStack();
});
}
else {
closeStack();
}
}
else if( canOpen ) { // stack is closed
canMoveHeroImage = false;
classie.add(bodyEl, 'view-full');
setTimeout(function() { classie.add(bodyEl, 'move-items'); }, 25);
bodyEl.style.height = stack.offsetHeight + 'px';
flkty.unbindDrag();
flkty.options.accessibility = false;
}
}
else if( classie.has(stack, 'stack-prev') ) {
flkty.previous(true);
}
else if( classie.has(stack, 'stack-next') ) {
flkty.next(true);
}
});
titleEl.addEventListener('mouseenter', function(ev) {
if( classie.has(stack, 'is-selected') ) {
canMoveHeroImage = false;
imghero.style.WebkitTransform = 'perspective(1000px) translate3d(0,0,0) rotate3d(1,1,1,0deg)';
imghero.style.transform = 'perspective(1000px) translate3d(0,0,0) rotate3d(1,1,1,0deg)';
}
});
titleEl.addEventListener('mouseleave', function(ev) {
// if current stack and it's not opened..
if( classie.has(stack, 'is-selected') && !classie.has(bodyEl, 'view-full') ) {
canMoveHeroImage = true;
}
});
});
window.addEventListener('mousemove', throttle(function(ev) {
if( !canMoveHeroImage ) return false;
var xVal = -1/(win.height/2)*ev.clientY + 1,
yVal = 1/(win.width/2)*ev.clientX - 1,
transX = 20/(win.width)*ev.clientX - 10,
transY = 20/(win.height)*ev.clientY - 10,
transZ = 100/(win.height)*ev.clientY - 50;
imghero.style.WebkitTransform = 'perspective(1000px) translate3d(' + transX + 'px,' + transY + 'px,' + transZ + 'px) rotate3d(' + xVal + ',' + yVal + ',0,2deg)';
imghero.style.transform = 'perspective(1000px) translate3d(' + transX + 'px,' + transY + 'px,' + transZ + 'px) rotate3d(' + xVal + ',' + yVal + ',0,2deg)';
}, 100));
// window resize
window.addEventListener( 'resize', throttle(function(ev) {
// recalculate window width/height
win = { width: window.innerWidth, height: window.innerHeight };
// reset body height if stack is opened
if( classie.has(bodyEl, 'view-full') ) { // stack is opened
bodyEl.style.height = stacks[flkty.selectedIndex].offsetHeight + 'px';
}
}, 50));
// Flickity events:
flkty.on('cellSelect', function() {
canOpen = false;
classie.remove(bodyEl, 'item-clickable');
var prevStack = stacksWrapper.querySelector('.stack-prev'),
nextStack = stacksWrapper.querySelector('.stack-next'),
selidx = flkty.selectedIndex,
cellsCount = flkty.cells.length,
previdx = selidx > 0 ? selidx - 1 : cellsCount - 1;
nextidx = selidx < cellsCount - 1 ? selidx + 1 : 0;
if( prevStack ) {
classie.remove(prevStack, 'stack-prev');
}
if( nextStack ) {
classie.remove(nextStack, 'stack-next');
}
classie.add(stacks[previdx], 'stack-prev');
classie.add(stacks[nextidx], 'stack-next');
});
flkty.on('dragStart', function() {
canOpen = false;
classie.remove(bodyEl, 'item-clickable');
});
flkty.on('settle', function() {
classie.add(bodyEl, 'item-clickable');
canOpen = true;
});
}
init();
})();
I wrapped the title and the first stack item in a div class .touch-me and it worked fairly well. I had previously tried to do this and received an error. But I may have mistyped something because it only made sense.
ISSUE: It works on mouseclick, but it is not working with touch on windows. I have untested it in any other environment because it will be deployed on a windows touch screen.
Although I cannot tell the layer not to close on touch when you swipe or touch the header image for the stack.... I'm afraid I do not have the skillset to properly modify the logic in the javascript since I do not entirely understand the plugins being used.

Is there any way of adapting this name-generating loop to run for a minimum number of seconds?

I'm using the following code (which has some Frog VLE API code in it; hopefully that's not too relevant) to pick a random student from a list.
This works well, but sometimes - given its random nature - it only runs for a very brief period of time. Would it be possible to loop this a number of times first, to ensure that it runs for X period of time as a minimum?
var Count = 0;
/* construct the array of people */
for (var i in data.users) {
for (var n = 0; n < data.users[i].Quantity; n++) {
var TempObj = { 'Count' : Count, 'Student_ID' : i, 'Student_Name' : data.users[i].Student_Name };
RewardPurchases.PurchasesArray[Count] = TempObj;
Count++;
}
}
... more code here, nothing relevant to the way the script works ...
$('button#random').click( function() {
/* first things first, play a drum-roll when the button is clicked! */
$('embed').remove();
$('body').append('<embed src="/user/74/177499.wav" autostart="true" hidden="true" loop="true">');
/* take the RewardPurchases.PurchasesArray and sort it so that there's no particular order */
RewardPurchases.PurchasesArray.sort(function() {return 0.5 - Math.random()})
/* remove the winner class for consecutive re-rolls */
$display.removeClass( "winner" );
$display.addClass( "spinner" );
/* determine the number of people in the array and calculate a random winner */
var total = RewardPurchases.PurchasesArray.length,
selected = Math.floor( Math.random() * total ),
i = 0;
/* work out how long each name should appear for, dependent upon how many people are in the array */
var timeout = ( 15000 / total );
/* run through the array of people ... */
for (i=0; i<total; i++) {
setTimeout((function(i){
return function(){
console.log( "timeout", i );
/* ... if the person in the array is a valid person! then display their name */
if (typeof RewardPurchases.PurchasesArray[i] === 'object' && typeof RewardPurchases.PurchasesArray[i] !== null) {
$display.text( "[" + RewardPurchases.PurchasesArray[i].Count + "] " + RewardPurchases.PurchasesArray[i].Student_Name.toUpperCase() );
/* if we encounter the winner, play a cheering wav and change the class of the display so that they appear in big, bold, red text */
if( i === selected ) {
$('embed').remove();
$('body').append('<embed src="/user/74/177086.wav" autostart="true" hidden="true" loop="false">');
$display.addClass( "winner" );
}
}
};
}(i)), i*timeout);
/* if the winner has been found, break the loop */
if( i === selected ) {
break;
}
}
} );
Thanks in advance,
You could do something like this :
function doforsec(msec, func) {
var curDate = new Date().getTime();
while ((new Date().getTime() - curDate) < msec) {
func();
}
}
doforsec(200, function() {
console.log(new Date().getSeconds())
});​
This executes the function given to doforsec again and again until the timeperiod specified (in milliseconds) is over. (first i had seconds, but i think milliseconds will be better)
JSfiddle
Because my deadline for this is.. well, around 8 hours from posting this.. I've decided to re-write the script and use a jQuery plugin:
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
$(document).ready(function(){
var staff = [ 'hardcoded', 'list', 'of', 'staff', 'members' ];
$('button#start').click( function() {
var $display = $('#display'),
$results = $('#results table');
$display.removeClass( "winner" );
$display.addClass( "spinner" );
var counter = 0,
rand = 0,
run_time = 10,
delay = ( run_time * 100 ) / staff.length,
loop_number = 5,
max_count = staff.length * loop_number;
$display.doTimeout( 'loop', delay, function() {
counter++;
var newRand = Math.floor( Math.random() * staff.length );
if ( rand === newRand ) {
rand = Math.floor( Math.random() * staff.length );
} else {
rand = newRand;
}
$(this).text( staff[rand] );
if ( counter < max_count ) { return true; }
else {
$('#results tr:last').after('<tr><td class="number">' + staff.length + '</td><td>' + staff[rand] + '</td></tr>');
staff.remove( rand );
}
});
$display.doTimeout( 'class', max_count * delay, function() {
$display.removeClass( "spinner" );
$display.addClass( "winner" );
});
});
});
After var timeout = ( 15000 / total ); insert the following, and remove the line for (i=0; i
var totalTime = 2000;
var timeOut= Math.Ceiling(totalTime/timeout);
var timesToDisplay = totalTime / timeOut;
var currentDisplay = 0;
for (currentDisplay = 0; currentDisplay < timesToDisplay; currentDisplay++) {
i = currentDisplay % total;

Categories