I'm a beginner in VueJS. And as part of my learning process, I'm building a knob for my Pomodoro app. This is my fiddle.
I copied the knob code from codepen, which is implemented using jquery. As you can see in the fiddle most of the job is done by jquery.
I need to try and do this using Vue.js, using its methods and states.
How to refactor this code to a better Vue.JS code? Any suggestions much appreciated.
Vue.component('timer', {
mounted() {
var knob = $('.knob');
var angle = 0;
var minangle = 0;
var maxangle = 270;
var xDirection = "";
var yDirection = "";
var oldX = 0;
var oldY = 0;
function moveKnob(direction) {
if(direction == 'up') {
if((angle + 2) <= maxangle) {
angle = angle + 2;
setAngle();
}
}
else if(direction == 'down') {
if((angle - 2) >= minangle) {
angle = angle - 2;
setAngle();
}
}
}
function setAngle() {
// rotate knob
knob.css({
'-moz-transform':'rotate('+angle+'deg)',
'-webkit-transform':'rotate('+angle+'deg)',
'-o-transform':'rotate('+angle+'deg)',
'-ms-transform':'rotate('+angle+'deg)',
'transform':'rotate('+angle+'deg)'
});
// highlight ticks
var activeTicks = (Math.round(angle / 10) + 1);
$('.tick').removeClass('activetick');
$('.tick').slice(0,activeTicks).addClass('activetick');
// update % value in text
var pc = Math.round((angle/270)*100);
$('.current-value').text(pc+'%');
}
var RAD2DEG = 180 / Math.PI;
knob.centerX = knob.offset().left + knob.width()/2;
knob.centerY = knob.offset().top + knob.height()/2;
var offset, dragging=false;
knob.mousedown(function(e) {
dragging = true;
offset = Math.atan2(knob.centerY - e.pageY, e.pageX - knob.centerX);
})
$(document).mouseup(function() {
dragging = false
})
$(document).mousemove(function(e) {
if (dragging) {
if (oldX < e.pageX) {
xDirection = "right";
} else {
xDirection = "left";
}
oldX = e.pageX;
if(xDirection === "left") {
moveKnob('down');
} else {
moveKnob('up');
}
return false;
}
})
}
});
This example runs without jQuery.
https://jsfiddle.net/guanzo/d6vashmu/6/
Declare all the variables you need in the data function.
Declare all functions under the methods property.
Declare variables that are derived from other variables in the computed property, such as knobStyle, activeTicks, and currentValue, which are all computed from angle. Whenever angle changes, these 3 computed properties will automatically update.
Regarding the general usage of Vue, you should focus on manipulating the data, and letting Vue update the DOM for you.
I'm looking for a thumbnail tiles scroller/slideshow/slider
Here is the example http://safari.to/clients
Really appreciate if anyone could help :) Thanks
When you see something on any website, its easy to inspect and see how they are doing it.
The website mentioned by you is doing it using their own script instead of a plug in
See the following code from http://safari.to/assets/js/script.js. You will also need to see how they are styling the sliders by inspecting their CSS code
// Agencies slide
var clients = Math.floor(Math.random() * 2) + 1; // nth-child indices start at 1
if ( clients == 1){
$('.agencies.clients').hide();
}
else
{
$('.brands.clients').hide();
}
$('.agencies menu a').bind({
click: function()
{
if(sliding) return false;
var pointer = $(this);
var width = $('.agencies .scroller li').length * 137;
var current = parseInt($('.agencies .scroller').css('left'));
var distance = 0;
if(pointer.is('.right-pointer'))
{
if(current == -1920) distance = current - 137;
else distance = current - 960;
if((width + current) < 960)
distance = current;
}
else
{
distance = current + 1097;
if(distance > 0)
distance = 0;
}
sliding = true;
$('.scroller').animate({
left: distance + 'px'
}, 300,
function()
{
sliding = false;
});
}
});
At the end or beginning of a Sencha Touch 2 carousel, a user can drag the item past where it should be able to go and display the white background (screenshot here: http://i.imgur.com/MkX0sam.png). I'm trying to disable this functionality, so a user can't drag past the end/beginning of a carousel.
I've attempted to do this with the various scrollable configurations, including the setup that is typically suggested for dealing with overscrolling
scrollable : {
direction: 'horizontal',
directionLock: true,
momentumEasing: {
momentum: {
acceleration: 30,
friction: 0.5
},
bounce: {
acceleration: 0.0001,
springTension: 0.9999,
},
minVelocity: 5
},
outOfBoundRestrictFactor: 0
}
The above configuration, especially outOfBoundRestrictFactor does stop the ability to drag past the end, but it also stops the ability to drag anywhere else in a carousel either...so that doesn't work. I've screwed around with all of the other configurations to no positive effect.
Unfortunately, I haven't been able to find much on modifying the configurations of dragging. Any help here would be awesomesauce.
What you need to do is override the onDrag functionality in Carousel. This is where the logic is to detect which direction the user is dragging, and where you can check if it is the first or last item.
Here is a class that does exactly what you want. The code you are interested in is right at the bottom of the function. The rest is simply taken from Ext.carousel.Carousel.
Ext.define('Ext.carousel.Custom', {
extend: 'Ext.carousel.Carousel',
onDrag: function(e) {
if (!this.isDragging) {
return;
}
var startOffset = this.dragStartOffset,
direction = this.getDirection(),
delta = direction === 'horizontal' ? e.deltaX : e.deltaY,
lastOffset = this.offset,
flickStartTime = this.flickStartTime,
dragDirection = this.dragDirection,
now = Ext.Date.now(),
currentActiveIndex = this.getActiveIndex(),
maxIndex = this.getMaxItemIndex(),
lastDragDirection = dragDirection,
offset;
if ((currentActiveIndex === 0 && delta > 0) || (currentActiveIndex === maxIndex && delta < 0)) {
delta *= 0.5;
}
offset = startOffset + delta;
if (offset > lastOffset) {
dragDirection = 1;
}
else if (offset < lastOffset) {
dragDirection = -1;
}
if (dragDirection !== lastDragDirection || (now - flickStartTime) > 300) {
this.flickStartOffset = lastOffset;
this.flickStartTime = now;
}
this.dragDirection = dragDirection;
// now that we have the dragDirection, we should use that to check if there
// is an item to drag to
if ((dragDirection == 1 && currentActiveIndex == 0) || (dragDirection == -1 && currentActiveIndex == maxIndex)) {
return;
}
this.setOffset(offset);
}
});
I have this code where the color changes on onmouseout and onmouseover events. However if I the move mouse over those boxes very fast the onmouseover function doesn't work properly and doesn't change the color. What could be the problem?
JS Fiddle Code
window.onload = function() {
var paper = Raphael(0, 0, 640, 540);
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
(function(i, j) {
var boxes = paper.rect(0 + (j * 320), 0 + (i * 270), 320, 270).attr({
fill: '#303030',
stroke: 'white'
});
boxes.node.onmouseover = function() {
boxes.animate({fill:'red'},500);
};
boxes.node.onmouseout = function() {
boxes.animate({fill:'#303030'},300);
};
})(i, j);
}
}
}
*Edit: Also how can I ensure that animation is applied to only 1 box even if I move the mouse quickly.
The mouseover animation is 200ms longer than the mouseout, so if you mouseover and mouseout in less than 200ms total, the animations run in parallel, and the mouseover one finishes last, leaving the color red.
Instead, add a .stop() before each .animate to stop the animations from competing:
boxes.node.onmouseover = function() {
boxes.stop().animate({fill:'red'},500);
};
boxes.node.onmouseout = function() {
boxes.stop().animate({fill:'#303030'},300);
};
See: http://jsfiddle.net/Eheqc/1/
I'm trying to add a button to a custom pallete to call a function "uiFileInputDlg" which is in the workspace that uses the widget. The upbtn appears on the pallete, but it is not triggering the DoUpload function which is connected in postcreate to then call on "uiFileInputDlg".
works flawlessly in firefox.
we're user dojo 1.7.2
-----------THE TEMPLATE-------------------------
<div class="dijitInline dijitColorPalette">
<div class="dijitColorPaletteInner" data-dojo-attach-point="divNode" role="grid" tabIndex="${tabIndex}">
</div>
<button type="button" id="upbtn"
data-dojo-type="dijit.form.Button"
data-dojo-props="id:'upbtn'"
data-dojo-attach-point="btnUpNode">
Upload New Image
</button>
</div>
-------------------------THE WIDGET--------------------------
//dojo.provide("meemli.UploadPalette");
define([ 'dojo/_base/declare',
'dijit/_WidgetBase',
'dijit/_TemplatedMixin',
'dojo/i18n!dijit/nls/common',
'dojo/text!./templates/UploadPalette.html',
'dijit/_WidgetsInTemplateMixin',
'dojo/_base/lang'
],
function(declare, w, t, i18n, template, witm, lang){
console.log('meemli.UploadPalette: Requiring dijit/nls/common.js INSTEAD OF dojo/nls/common' + i18n.invalidMessage);
return declare("meemli.UploadPalette",
[dijit._Widget, dijit._Templated],
{
// summary: A keyboard accessible color-picking widget
// description:
// Grid showing various colors, so the user can pick a certain color
// Can be used standalone, or as a popup.
//
// example:
// | <div dojoType="dijit.ColorPalette"></div>
//
// example:
// | var picker = new dijit.ColorPalette({ },srcNode);
// | picker.startup();
//
// defaultTimeout: Number
// number of milliseconds before a held key or button becomes typematic
defaultTimeout: 500,
// timeoutChangeRate: Number
// fraction of time used to change the typematic timer between events
// 1.0 means that each typematic event fires at defaultTimeout intervals
// < 1.0 means that each typematic event fires at an increasing faster rate
timeoutChangeRate: 0.90,
// palette: String
// Size of grid, either "7x10" or "3x4".
palette: "3x3",
//_value: String
// The value of the selected color.
value: null,
//_currentFocus: Integer
// Index of the currently focused color.
_currentFocus: 0,
// _xDim: Integer
// This is the number of colors horizontally across.
_xDim: null,
// _yDim: Integer
/// This is the number of colors vertically down.
_yDim: null,
// _palettes: Map
// This represents the value of the colors.
// The first level is a hashmap of the different arrays available
// The next two dimensions represent the columns and rows of colors.
_palettes: {
"3x3": [],
"3x2": ["/images/icons/1.png", "/images/icons/2.png", "/images/icons/3.png","/images/icons/4.png", "/images/icons/5.png", "/images/icons/6.png"]
},
// _imagePaths: Map
// This is stores the path to the palette images
// _imagePaths: {
// "3x3": dojo.moduleUrl("dijit", "templates/icons3x3.png")
// },
// _paletteCoords: Map
// This is a map that is used to calculate the coordinates of the
// images that make up the palette.
_paletteCoords: {
"leftOffset": 3, "topOffset": 3,
"cWidth": 50, "cHeight": 50
},
// templatePath: String
// Path to the template of this widget.
// templateString: dojo.cache("meemli", "templates/UploadPalette.html"),
templateString: template,
// _paletteDims: Object
// Size of the supported palettes for alignment purposes.
_paletteDims: {
"3x3": {"width": "156px", "height": "156px"}, // 48*3 + 3px left/top border + 3px right/bottom border...
"3x2": {"width": "156px", "height": "109px"} // 48*3 + 3px left/top border + 3px right/bottom border...
},
// tabIndex: String
// Widget tabindex.
maxCols: 3,
tabIndex: "0",
_curIndex: 0,
DoUpload: function(){
alert('hello');
uiFileInputDlg(); // function out in the workspace
},
_addImage: function(url) {
row = Math.floor(this._curIndex / this.maxCols);
col = this._curIndex - (row * this.maxCols);
this._curIndex++;
this._yDim = Math.floor(this._curIndex / this.maxCols);
this._xDim = this._curIndex - (row * this.maxCols);
var imgNode = dojo.doc.createElement("img");
imgNode.src = url;
//imgNode.style.height = imgNode.style.width = "48px";
var cellNode = dojo.doc.createElement("span");
cellNode.appendChild(imgNode);
cellNode.connectionRefs = new Array();
dojo.forEach(["Dijitclick", "MouseEnter", "Focus", "Blur"], function(handler) {
cellNode.connectionRefs.push(this.connect(cellNode, "on" + handler.toLowerCase(), "_onCell" + handler));
}, this);
this.divNode.appendChild(cellNode);
var cellStyle = cellNode.style;
cellStyle.top = this._paletteCoords.topOffset + (row * this._paletteCoords.cHeight) + "px";
cellStyle.left = this._paletteCoords.leftOffset + (col * this._paletteCoords.cWidth) + "px";
cellStyle.height = this._paletteCoords.cHeight + "px";
cellStyle.width = this._paletteCoords.cWidth + "px";
// console.debug( "tlhw: " + cellStyle.top + ", " + cellStyle.left + ", " + cellStyle.height + ", " + cellStyle.width );
// adjust size when the bits come...
// this.xh = this.xw = "32px";
//console.log('this.xh => ' + this.xh);
dojo.connect( imgNode,"onload", this, function() {
//console.log('IN: CONNECT...this.xh => ' + this.xh);
this.xh = imgNode.height;
this.xw = imgNode.width;
this.xh = (this.xh==0) ? this.xh="32px" : (this.xh + "");
this.xw = (this.xw==0) ? this.xw="32px" : (this.xw + "");
// var h = parseInt( this.xh );
// var w = parseInt( this.xw );
var hArr = this.xh.split('p');
var wArr = this.xw.split('p');
var h =hArr[0];
var w = wArr[0];
var THUMBNAIL_MAX_WIDTH = 50;
var THUMBNAIL_MAX_HEIGHT = 50;
var hLim = Math.min(THUMBNAIL_MAX_HEIGHT, this._paletteCoords.cHeight);
var wLim = Math.min(THUMBNAIL_MAX_WIDTH, this._paletteCoords.cWidth);
var scale = 1.0;
if( h > hLim || w > wLim ) {
if( h / w < 1.0 ) { // width is bigger than height
scale = wLim / w;
}
else {
scale = hLim / h;
}
}
imgNode.style.height = (scale * h) + "px";
imgNode.style.width = (scale * w) + "px";
console.debug( imgNode.src + ' loaded.'
+ "old: h " + h + ", w " + w + ", scale " + scale
+ ". new: h " + imgNode.style.height + ", w " + imgNode.style.width );
} );
if(dojo.isIE){
// hack to force event firing in IE
// image quirks doc'd in dojox/image/Lightbox.js :: show: function.
// imgNode.src = imgNode.src;
}
dojo.attr(cellNode, "tabindex", "-1");
dojo.addClass(cellNode, "imagePaletteCell");
dijit.setWaiRole(cellNode, "gridcell");
cellNode.index = this._cellNodes.length;
this._cellNodes.push(cellNode);
},
_clearImages: function() {
for(var i = 0; i < this._cellNodes.length; i++) {
this._cellNodes[i].parentNode.removeChild(this._cellNodes[i]);
}
this._currentFocus = 0;
this._curIndex = 0;
this._yDim = 0;
this._xDim = 0;
this._cellNodes = [];
},
setImages: function(imageList) {
this._clearImages();
for(var i = 0; i < imageList.length; i++) {
this._addImage(imageList[i]);
}
},
postCreate: function(){
// A name has to be given to the colorMap, this needs to be unique per Palette.
dojo.mixin(this.divNode.style, this._paletteDims[this.palette]);
// this.imageNode.setAttribute("src", this._imagePaths[this.palette]);
this.domNode.style.position = "relative";
this._cellNodes = [];
this.setImages(this._palettes[this.palette]);
this.connect(this.divNode, "onfocus", "_onDivNodeFocus");
this.connect(this.btnUpNode, "onclick", "DoUpload");
// Now set all events
// The palette itself is navigated to with the tab key on the keyboard
// Keyboard navigation within the Palette is with the arrow keys
// Spacebar selects the color.
// For the up key the index is changed by negative the x dimension.
var keyIncrementMap = {
UP_ARROW: -this._xDim,
// The down key the index is increase by the x dimension.
DOWN_ARROW: this._xDim,
// Right and left move the index by 1.
RIGHT_ARROW: 1,
LEFT_ARROW: -1
};
for(var key in keyIncrementMap){
this._connects.push(dijit.typematic.addKeyListener(this.domNode,
{keyCode:dojo.keys[key], ctrlKey:false, altKey:false, shiftKey:false},
this,
function(){
var increment = keyIncrementMap[key];
return function(count){ this._navigateByKey(increment, count); };
}(),
this.timeoutChangeRate, this.defaultTimeout));
}
},
focus: function(){
// summary:
// Focus this ColorPalette. Puts focus on the first swatch.
this._focusFirst();
},
onChange: function(url, hsz, wsz){
// summary:
// Callback when a image is selected.
// url, hsz, wsz, strings
// height and width string .
// console.debug("img selected: "+url);
},
_focusFirst: function(){
this._currentFocus = 0;
var cellNode = this._cellNodes[this._currentFocus];
window.setTimeout(function(){dijit.focus(cellNode);}, 0);
},
_onDivNodeFocus: function(evt){
// focus bubbles on Firefox 2, so just make sure that focus has really
// gone to the container
if(evt.target === this.divNode){
this._focusFirst();
}
},
_onFocus: function(){
// while focus is on the palette, set its tabindex to -1 so that on a
// shift-tab from a cell, the container is not in the tab order
dojo.attr(this.divNode, "tabindex", "-1");
},
_onBlur: function(){
this._removeCellHighlight(this._currentFocus);
// when focus leaves the palette, restore its tabindex, since it was
// modified by _onFocus().
dojo.attr(this.divNode, "tabindex", this.tabIndex);
},
_onCellDijitclick: function(/*Event*/ evt){
// summary:
// Handler for click, enter key & space key. Selects the color.
// evt:
// The event.
var target = evt.currentTarget;
if (this._currentFocus != target.index){
this._currentFocus = target.index;
window.setTimeout(function(){dijit.focus(target);}, 0);
}
this._selectColor(target);
dojo.stopEvent(evt);
},
_onCellMouseEnter: function(/*Event*/ evt){
// summary:
// Handler for onMouseOver. Put focus on the color under the mouse.
// evt:
// The mouse event.
var target = evt.currentTarget;
window.setTimeout(function(){dijit.focus(target);}, 0);
},
_onCellFocus: function(/*Event*/ evt){
// summary:
// Handler for onFocus. Removes highlight of
// the color that just lost focus, and highlights
// the new color.
// evt:
// The focus event.
this._removeCellHighlight(this._currentFocus);
this._currentFocus = evt.currentTarget.index;
dojo.addClass(evt.currentTarget, "imagePaletteCellHighlight");
},
_onCellBlur: function(/*Event*/ evt){
// summary:
// needed for Firefox 2 on Mac OS X
this._removeCellHighlight(this._currentFocus);
},
_removeCellHighlight: function(index){
dojo.removeClass(this._cellNodes[index], "imagePaletteCellHighlight");
},
_selectColor: function(selectNode){
// summary:
// This selects a color. It triggers the onChange event
// area:
// The area node that covers the color being selected.
var img = selectNode.getElementsByTagName("img")[0];
this.onChange(this.value = img.src, this.xh, this.xw);
},
_navigateByKey: function(increment, typeCount){
// summary:
// This is the callback for typematic.
// It changes the focus and the highlighed color.
// increment:
// How much the key is navigated.
// typeCount:
// How many times typematic has fired.
// typecount == -1 means the key is released.
if(typeCount == -1){ return; }
var newFocusIndex = this._currentFocus + increment;
if(newFocusIndex < this._cellNodes.length && newFocusIndex > -1)
{
var focusNode = this._cellNodes[newFocusIndex];
focusNode.focus();
}
}
});
});
Update
this.connect(this.btnUpNode, "onclick", "DoUpload");
to be
this.connect(this.btnUpNode, "onClick", "DoUpload");
onclick is a dom event, onClick is a dijit event. Since you are using a dijit button you want to use the latter.