refact about page
This commit is contained in:
parent
8bd6545c1b
commit
3042c7c08e
1
Gemfile
1
Gemfile
|
@ -12,6 +12,7 @@ gem 'uglifier', '>= 1.3.0'
|
|||
gem 'jquery-rails'
|
||||
gem 'foundation-rails', '~> 5.2.1'
|
||||
gem 'foundation-icons-sass-rails'
|
||||
gem 'font-awesome-sass'
|
||||
|
||||
gem 'mongoid'
|
||||
gem 'mongoid-pagination'
|
||||
|
|
|
@ -73,6 +73,8 @@ GEM
|
|||
ffi (1.9.5)
|
||||
figaro (1.0.0)
|
||||
thor (~> 0.14)
|
||||
font-awesome-sass (4.0.2)
|
||||
sass-rails (>= 3.1.1)
|
||||
formatador (0.2.5)
|
||||
foundation-icons-sass-rails (3.0.0)
|
||||
railties (>= 3.1.1)
|
||||
|
@ -285,6 +287,7 @@ DEPENDENCIES
|
|||
database_cleaner
|
||||
factory_girl_rails
|
||||
figaro
|
||||
font-awesome-sass
|
||||
foundation-icons-sass-rails
|
||||
foundation-rails (~> 5.2.1)
|
||||
guard
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 108 KiB |
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="图形" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1024px" height="1024px" viewBox="0 0 1024 1024" enable-background="new 0 0 1024 1024" xml:space="preserve">
|
||||
<path fill="#219AB3" d="M926.917973 774.19392C959.65184 774.19392 986.19392 747.65184 986.19392 714.917973L986.19392-114.917973C986.19392-147.65184 959.65184-174.19392 926.917973-174.19392L97.082027-174.19392C64.34816-174.19392 37.80608-147.65184 37.80608-114.917973L37.80608 714.917973C37.80608 747.65184 64.34816 774.19392 97.082027 774.19392zM176.653653 635.80032 176.653653 559.321173 825.658027 559.321173 825.658027 635.80032zM217.719467 495.853653 217.719467 183.91936 273.524053 183.91936 341.292373 41.60384 157.259093 41.60384 157.259093-33.417813 842.949973-33.417813 842.949973 41.60384 654.226773 41.60384 722.899627 183.91936 783.67744 183.91936 783.67744 495.853653zM684.885333 419.108267 684.885333 258.012587 312.576 258.012587 312.576 419.108267zM570.770773 41.60384 426.653013 41.60384 359.621973 183.91936 639.443627 183.91936z" transform="translate(0, 812) scale(1, -1)"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 86 KiB |
|
@ -0,0 +1,589 @@
|
|||
/**
|
||||
* x is a value between 0 and 1, indicating where in the animation you are.
|
||||
*/
|
||||
var duScrollDefaultEasing = function (x) {
|
||||
'use strict';
|
||||
|
||||
if(x < 0.5) {
|
||||
return Math.pow(x*2, 2)/2;
|
||||
}
|
||||
return 1-Math.pow((1-x)*2, 2)/2;
|
||||
};
|
||||
|
||||
angular.module('duScroll', [
|
||||
'duScroll.scrollspy',
|
||||
'duScroll.smoothScroll',
|
||||
'duScroll.scrollContainer',
|
||||
'duScroll.spyContext',
|
||||
'duScroll.scrollHelpers'
|
||||
])
|
||||
//Default animation duration for smoothScroll directive
|
||||
.value('duScrollDuration', 350)
|
||||
//Scrollspy debounce interval, set to 0 to disable
|
||||
.value('duScrollSpyWait', 100)
|
||||
//Wether or not multiple scrollspies can be active at once
|
||||
.value('duScrollGreedy', false)
|
||||
//Default offset for smoothScroll directive
|
||||
.value('duScrollOffset', 0)
|
||||
//Default easing function for scroll animation
|
||||
.value('duScrollEasing', duScrollDefaultEasing);
|
||||
|
||||
|
||||
angular.module('duScroll.scrollHelpers', ['duScroll.requestAnimation'])
|
||||
.run(["$window", "$q", "cancelAnimation", "requestAnimation", "duScrollEasing", "duScrollDuration", "duScrollOffset", function($window, $q, cancelAnimation, requestAnimation, duScrollEasing, duScrollDuration, duScrollOffset) {
|
||||
'use strict';
|
||||
|
||||
var proto = angular.element.prototype;
|
||||
|
||||
var isDocument = function(el) {
|
||||
return (typeof HTMLDocument !== 'undefined' && el instanceof HTMLDocument) || (el.nodeType && el.nodeType === el.DOCUMENT_NODE);
|
||||
};
|
||||
|
||||
var isElement = function(el) {
|
||||
return (typeof HTMLElement !== 'undefined' && el instanceof HTMLElement) || (el.nodeType && el.nodeType === el.ELEMENT_NODE);
|
||||
};
|
||||
|
||||
var unwrap = function(el) {
|
||||
return isElement(el) || isDocument(el) ? el : el[0];
|
||||
};
|
||||
|
||||
proto.scrollTo = function(left, top, duration, easing) {
|
||||
var aliasFn;
|
||||
if(angular.isElement(left)) {
|
||||
aliasFn = this.scrollToElement;
|
||||
} else if(duration) {
|
||||
aliasFn = this.scrollToAnimated;
|
||||
}
|
||||
if(aliasFn) {
|
||||
return aliasFn.apply(this, arguments);
|
||||
}
|
||||
var el = unwrap(this);
|
||||
if(isDocument(el)) {
|
||||
return $window.scrollTo(left, top);
|
||||
}
|
||||
el.scrollLeft = left;
|
||||
el.scrollTop = top;
|
||||
};
|
||||
|
||||
var scrollAnimation, deferred;
|
||||
proto.scrollToAnimated = function(left, top, duration, easing) {
|
||||
if(duration && !easing) {
|
||||
easing = duScrollEasing;
|
||||
}
|
||||
var startLeft = this.scrollLeft(),
|
||||
startTop = this.scrollTop(),
|
||||
deltaLeft = Math.round(left - startLeft),
|
||||
deltaTop = Math.round(top - startTop);
|
||||
|
||||
var startTime = null;
|
||||
var el = this;
|
||||
|
||||
var cancelOnEvents = 'scroll mousedown mousewheel touchmove keydown';
|
||||
var cancelScrollAnimation = function($event) {
|
||||
if (!$event || $event.which > 0) {
|
||||
el.unbind(cancelOnEvents, cancelScrollAnimation);
|
||||
cancelAnimation(scrollAnimation);
|
||||
deferred.reject();
|
||||
scrollAnimation = null;
|
||||
}
|
||||
};
|
||||
|
||||
if(scrollAnimation) {
|
||||
cancelScrollAnimation();
|
||||
}
|
||||
deferred = $q.defer();
|
||||
|
||||
if(!deltaLeft && !deltaTop) {
|
||||
deferred.resolve();
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
var animationStep = function(timestamp) {
|
||||
if (startTime === null) {
|
||||
startTime = timestamp;
|
||||
}
|
||||
|
||||
var progress = timestamp - startTime;
|
||||
var percent = (progress >= duration ? 1 : easing(progress/duration));
|
||||
|
||||
el.scrollTo(
|
||||
startLeft + Math.ceil(deltaLeft * percent),
|
||||
startTop + Math.ceil(deltaTop * percent)
|
||||
);
|
||||
if(percent < 1) {
|
||||
scrollAnimation = requestAnimation(animationStep);
|
||||
} else {
|
||||
el.unbind(cancelOnEvents, cancelScrollAnimation);
|
||||
scrollAnimation = null;
|
||||
deferred.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
//Fix random mobile safari bug when scrolling to top by hitting status bar
|
||||
el.scrollTo(startLeft, startTop);
|
||||
|
||||
el.bind(cancelOnEvents, cancelScrollAnimation);
|
||||
|
||||
scrollAnimation = requestAnimation(animationStep);
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
proto.scrollToElement = function(target, offset, duration, easing) {
|
||||
var el = unwrap(this);
|
||||
if(!angular.isNumber(offset) || isNaN(offset)) {
|
||||
offset = duScrollOffset;
|
||||
}
|
||||
var top = this.scrollTop() + unwrap(target).getBoundingClientRect().top - offset;
|
||||
if(isElement(el)) {
|
||||
top -= el.getBoundingClientRect().top;
|
||||
}
|
||||
return this.scrollTo(0, top, duration, easing);
|
||||
};
|
||||
|
||||
var overloaders = {
|
||||
scrollLeft: function(value, duration, easing) {
|
||||
if(angular.isNumber(value)) {
|
||||
return this.scrollTo(value, this.scrollTop(), duration, easing);
|
||||
}
|
||||
var el = unwrap(this);
|
||||
if(isDocument(el)) {
|
||||
return $window.scrollX || document.documentElement.scrollLeft || document.body.scrollLeft;
|
||||
}
|
||||
return el.scrollLeft;
|
||||
},
|
||||
scrollTop: function(value, duration, easing) {
|
||||
if(angular.isNumber(value)) {
|
||||
return this.scrollTo(this.scrollTop(), value, duration, easing);
|
||||
}
|
||||
var el = unwrap(this);
|
||||
if(isDocument(el)) {
|
||||
return $window.scrollY || document.documentElement.scrollTop || document.body.scrollTop;
|
||||
}
|
||||
return el.scrollTop;
|
||||
}
|
||||
};
|
||||
|
||||
proto.scrollToElementAnimated = function(target, offset, duration, easing) {
|
||||
return this.scrollToElement(target, offset, duration || duScrollDuration, easing);
|
||||
};
|
||||
|
||||
proto.scrollTopAnimated = function(top, duration, easing) {
|
||||
return this.scrollTop(top, duration || duScrollDuration, easing);
|
||||
};
|
||||
|
||||
proto.scrollLeftAnimated = function(left, duration, easing) {
|
||||
return this.scrollLeft(left, duration || duScrollDuration, easing);
|
||||
};
|
||||
|
||||
//Add duration and easing functionality to existing jQuery getter/setters
|
||||
var overloadScrollPos = function(superFn, overloadFn) {
|
||||
return function(value, duration, easing) {
|
||||
if(duration) {
|
||||
return overloadFn.apply(this, arguments);
|
||||
}
|
||||
return superFn.apply(this, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
for(var methodName in overloaders) {
|
||||
proto[methodName] = (proto[methodName] ? overloadScrollPos(proto[methodName], overloaders[methodName]) : overloaders[methodName]);
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
//Adapted from https://gist.github.com/paulirish/1579671
|
||||
angular.module('duScroll.polyfill', [])
|
||||
.factory('polyfill', ["$window", function($window) {
|
||||
'use strict';
|
||||
|
||||
var vendors = ['webkit', 'moz', 'o', 'ms'];
|
||||
|
||||
return function(fnName, fallback) {
|
||||
if($window[fnName]) {
|
||||
return $window[fnName];
|
||||
}
|
||||
var suffix = fnName.substr(0, 1).toUpperCase() + fnName.substr(1);
|
||||
for(var key, i = 0; i < vendors.length; i++) {
|
||||
key = vendors[i]+suffix;
|
||||
if($window[key]) {
|
||||
return $window[key];
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
};
|
||||
}]);
|
||||
|
||||
angular.module('duScroll.requestAnimation', ['duScroll.polyfill'])
|
||||
.factory('requestAnimation', ["polyfill", "$timeout", function(polyfill, $timeout) {
|
||||
'use strict';
|
||||
|
||||
var lastTime = 0;
|
||||
var fallback = function(callback, element) {
|
||||
var currTime = new Date().getTime();
|
||||
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
||||
var id = $timeout(function() { callback(currTime + timeToCall); },
|
||||
timeToCall);
|
||||
lastTime = currTime + timeToCall;
|
||||
return id;
|
||||
};
|
||||
|
||||
return polyfill('requestAnimationFrame', fallback);
|
||||
}])
|
||||
.factory('cancelAnimation', ["polyfill", "$timeout", function(polyfill, $timeout) {
|
||||
'use strict';
|
||||
|
||||
var fallback = function(promise) {
|
||||
$timeout.cancel(promise);
|
||||
};
|
||||
|
||||
return polyfill('cancelAnimationFrame', fallback);
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.spyAPI', ['duScroll.scrollContainerAPI'])
|
||||
.factory('spyAPI', ["$rootScope", "$timeout", "scrollContainerAPI", "duScrollGreedy", "duScrollSpyWait", function($rootScope, $timeout, scrollContainerAPI, duScrollGreedy, duScrollSpyWait) {
|
||||
'use strict';
|
||||
|
||||
var createScrollHandler = function(context) {
|
||||
var timer = false, queued = false;
|
||||
var handler = function() {
|
||||
queued = false;
|
||||
var container = context.container,
|
||||
containerEl = container[0],
|
||||
containerOffset = 0;
|
||||
|
||||
if (typeof HTMLElement !== 'undefined' && containerEl instanceof HTMLElement || containerEl.nodeType && containerEl.nodeType === containerEl.ELEMENT_NODE) {
|
||||
containerOffset = containerEl.getBoundingClientRect().top;
|
||||
}
|
||||
|
||||
var i, currentlyActive, toBeActive, spies, spy, pos;
|
||||
spies = context.spies;
|
||||
currentlyActive = context.currentlyActive;
|
||||
toBeActive = undefined;
|
||||
|
||||
for(i = 0; i < spies.length; i++) {
|
||||
spy = spies[i];
|
||||
pos = spy.getTargetPosition();
|
||||
if (!pos) continue;
|
||||
|
||||
if(pos.top + spy.offset - containerOffset < 20 && (pos.top*-1 + containerOffset) < pos.height) {
|
||||
if(!toBeActive || toBeActive.top < pos.top) {
|
||||
toBeActive = {
|
||||
top: pos.top,
|
||||
spy: spy
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if(toBeActive) {
|
||||
toBeActive = toBeActive.spy;
|
||||
}
|
||||
if(currentlyActive === toBeActive || (duScrollGreedy && !toBeActive)) return;
|
||||
if(currentlyActive) {
|
||||
currentlyActive.$element.removeClass('active');
|
||||
$rootScope.$broadcast('duScrollspy:becameInactive', currentlyActive.$element);
|
||||
}
|
||||
if(toBeActive) {
|
||||
toBeActive.$element.addClass('active');
|
||||
$rootScope.$broadcast('duScrollspy:becameActive', toBeActive.$element);
|
||||
}
|
||||
context.currentlyActive = toBeActive;
|
||||
};
|
||||
|
||||
if(!duScrollSpyWait) {
|
||||
return handler;
|
||||
}
|
||||
|
||||
//Debounce for potential performance savings
|
||||
return function() {
|
||||
if(!timer) {
|
||||
handler();
|
||||
timer = $timeout(function() {
|
||||
timer = false;
|
||||
if(queued) {
|
||||
handler();
|
||||
}
|
||||
}, duScrollSpyWait, false);
|
||||
} else {
|
||||
queued = true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var contexts = {};
|
||||
|
||||
var createContext = function($scope) {
|
||||
var id = $scope.$id;
|
||||
var context = {
|
||||
spies: []
|
||||
};
|
||||
|
||||
context.handler = createScrollHandler(context);
|
||||
contexts[id] = context;
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
destroyContext($scope);
|
||||
});
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
var destroyContext = function($scope) {
|
||||
var id = $scope.$id;
|
||||
var context = contexts[id], container = context.container;
|
||||
if(container) {
|
||||
container.off('scroll', context.handler);
|
||||
}
|
||||
delete contexts[id];
|
||||
};
|
||||
|
||||
var defaultContextId = createContext($rootScope);
|
||||
|
||||
var getContextForScope = function(scope) {
|
||||
if(contexts[scope.$id]) {
|
||||
return contexts[scope.$id];
|
||||
}
|
||||
if(scope.$parent) {
|
||||
return getContextForScope(scope.$parent);
|
||||
}
|
||||
return contexts[defaultContextId];
|
||||
};
|
||||
|
||||
var getContextForSpy = function(spy) {
|
||||
var context, contextId, scope = spy.$element.scope();
|
||||
if(scope) {
|
||||
return getContextForScope(scope);
|
||||
}
|
||||
//No scope, most likely destroyed
|
||||
for(contextId in contexts) {
|
||||
context = contexts[contextId];
|
||||
if(context.spies.indexOf(spy) !== -1) {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var isElementInDocument = function(element) {
|
||||
while (element.parentNode) {
|
||||
element = element.parentNode;
|
||||
if (element === document) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var addSpy = function(spy) {
|
||||
var context = getContextForSpy(spy);
|
||||
if (!context) return;
|
||||
context.spies.push(spy);
|
||||
if (!context.container || !isElementInDocument(context.container)) {
|
||||
if(context.container) {
|
||||
context.container.off('scroll', context.handler);
|
||||
}
|
||||
context.container = scrollContainerAPI.getContainer(spy.$element.scope());
|
||||
context.container.on('scroll', context.handler).triggerHandler('scroll');
|
||||
}
|
||||
};
|
||||
|
||||
var removeSpy = function(spy) {
|
||||
var context = getContextForSpy(spy);
|
||||
if(spy === context.currentlyActive) {
|
||||
context.currentlyActive = null;
|
||||
}
|
||||
var i = context.spies.indexOf(spy);
|
||||
if(i !== -1) {
|
||||
context.spies.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
addSpy: addSpy,
|
||||
removeSpy: removeSpy,
|
||||
createContext: createContext,
|
||||
destroyContext: destroyContext,
|
||||
getContextForScope: getContextForScope
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.scrollContainerAPI', [])
|
||||
.factory('scrollContainerAPI', ["$document", function($document) {
|
||||
'use strict';
|
||||
|
||||
var containers = {};
|
||||
|
||||
var setContainer = function(scope, element) {
|
||||
var id = scope.$id;
|
||||
containers[id] = element;
|
||||
return id;
|
||||
};
|
||||
|
||||
var getContainerId = function(scope) {
|
||||
if(containers[scope.$id]) {
|
||||
return scope.$id;
|
||||
}
|
||||
if(scope.$parent) {
|
||||
return getContainerId(scope.$parent);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
var getContainer = function(scope) {
|
||||
var id = getContainerId(scope);
|
||||
return id ? containers[id] : $document;
|
||||
};
|
||||
|
||||
var removeContainer = function(scope) {
|
||||
var id = getContainerId(scope);
|
||||
if(id) {
|
||||
delete containers[id];
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
getContainerId: getContainerId,
|
||||
getContainer: getContainer,
|
||||
setContainer: setContainer,
|
||||
removeContainer: removeContainer
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.smoothScroll', ['duScroll.scrollHelpers', 'duScroll.scrollContainerAPI'])
|
||||
.directive('duSmoothScroll', ["duScrollDuration", "duScrollOffset", "scrollContainerAPI", function(duScrollDuration, duScrollOffset, scrollContainerAPI) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
link : function($scope, $element, $attr) {
|
||||
$element.on('click', function(e) {
|
||||
if(!$attr.href || $attr.href.indexOf('#') === -1) return;
|
||||
|
||||
var target = document.getElementById($attr.href.replace(/.*(?=#[^\s]+$)/, '').substring(1));
|
||||
if(!target || !target.getBoundingClientRect) return;
|
||||
|
||||
if (e.stopPropagation) e.stopPropagation();
|
||||
if (e.preventDefault) e.preventDefault();
|
||||
|
||||
var offset = $attr.offset ? parseInt($attr.offset, 10) : duScrollOffset;
|
||||
var duration = $attr.duration ? parseInt($attr.duration, 10) : duScrollDuration;
|
||||
var container = scrollContainerAPI.getContainer($scope);
|
||||
|
||||
container.scrollToElement(
|
||||
angular.element(target),
|
||||
isNaN(offset) ? 0 : offset,
|
||||
isNaN(duration) ? 0 : duration
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.spyContext', ['duScroll.spyAPI'])
|
||||
.directive('duSpyContext', ["spyAPI", function(spyAPI) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: true,
|
||||
compile: function compile(tElement, tAttrs, transclude) {
|
||||
return {
|
||||
pre: function preLink($scope, iElement, iAttrs, controller) {
|
||||
spyAPI.createContext($scope);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.scrollContainer', ['duScroll.scrollContainerAPI'])
|
||||
.directive('duScrollContainer', ["scrollContainerAPI", function(scrollContainerAPI){
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: true,
|
||||
compile: function compile(tElement, tAttrs, transclude) {
|
||||
return {
|
||||
pre: function preLink($scope, iElement, iAttrs, controller) {
|
||||
iAttrs.$observe('duScrollContainer', function(element) {
|
||||
if(angular.isString(element)) {
|
||||
element = document.getElementById(element);
|
||||
}
|
||||
|
||||
element = (angular.isElement(element) ? angular.element(element) : iElement);
|
||||
scrollContainerAPI.setContainer($scope, element);
|
||||
$scope.$on('$destroy', function() {
|
||||
scrollContainerAPI.removeContainer($scope);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
angular.module('duScroll.scrollspy', ['duScroll.spyAPI'])
|
||||
.directive('duScrollspy', ["spyAPI", "duScrollOffset", "$timeout", "$rootScope", function(spyAPI, duScrollOffset, $timeout, $rootScope) {
|
||||
'use strict';
|
||||
|
||||
var Spy = function(targetElementOrId, $element, offset) {
|
||||
if(angular.isElement(targetElementOrId)) {
|
||||
this.target = targetElementOrId;
|
||||
} else if(angular.isString(targetElementOrId)) {
|
||||
this.targetId = targetElementOrId;
|
||||
}
|
||||
this.$element = $element;
|
||||
this.offset = offset;
|
||||
};
|
||||
|
||||
Spy.prototype.getTargetElement = function() {
|
||||
if (!this.target && this.targetId) {
|
||||
this.target = document.getElementById(this.targetId);
|
||||
}
|
||||
return this.target;
|
||||
};
|
||||
|
||||
Spy.prototype.getTargetPosition = function() {
|
||||
var target = this.getTargetElement();
|
||||
if(target) {
|
||||
return target.getBoundingClientRect();
|
||||
}
|
||||
};
|
||||
|
||||
Spy.prototype.flushTargetCache = function() {
|
||||
if(this.targetId) {
|
||||
this.target = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
link: function ($scope, $element, $attr) {
|
||||
var href = $attr.ngHref || $attr.href;
|
||||
var targetId;
|
||||
|
||||
if (href && href.indexOf('#') !== -1) {
|
||||
targetId = href.replace(/.*(?=#[^\s]+$)/, '').substring(1);
|
||||
} else if($attr.duScrollspy) {
|
||||
targetId = $attr.duScrollspy;
|
||||
}
|
||||
if(!targetId) return;
|
||||
|
||||
// Run this in the next execution loop so that the scroll context has a chance
|
||||
// to initialize
|
||||
$timeout(function() {
|
||||
var spy = new Spy(targetId, $element, -($attr.offset ? parseInt($attr.offset, 10) : duScrollOffset));
|
||||
spyAPI.addSpy(spy);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
spyAPI.removeSpy(spy);
|
||||
});
|
||||
$scope.$on('$locationChangeSuccess', spy.flushTargetCache.bind(spy));
|
||||
$rootScope.$on('$stateChangeSuccess', spy.flushTargetCache.bind(spy));
|
||||
}, 0, false);
|
||||
}
|
||||
};
|
||||
}]);
|
|
@ -2,10 +2,12 @@
|
|||
#= require angular-cookies
|
||||
#= require angular-resource
|
||||
#= require angular-sanitize
|
||||
#= require angular-scroll
|
||||
#= require_self
|
||||
#= require_tree ./angularjs
|
||||
|
||||
@app = angular.module('app', ['ngCookies', 'ngSanitize'])
|
||||
@app = angular.module('app', ['ngCookies', 'ngSanitize', 'duScroll'])
|
||||
@app.value('duScrollOffset', 30)
|
||||
|
||||
@app.config(["$httpProvider", (provider) ->
|
||||
provider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
@app.controller 'AboutScrollController', [ '$scope', '$document', ($scope, $document)->
|
||||
about_id = angular.element(document.getElementById('about'))
|
||||
|
||||
$scope.to_about = ()->
|
||||
$document.scrollToElementAnimated(about_id)
|
||||
]
|
|
@ -3,6 +3,7 @@
|
|||
//= require foundation/foundation
|
||||
//= require foundation/foundation.topbar
|
||||
//= require foundation/foundation.offcanvas
|
||||
//= require foundation/foundation.magellan
|
||||
//= require angularjs
|
||||
//= require 'jquery.html5-fileupload'
|
||||
//= require_tree .
|
||||
|
|
|
@ -20,3 +20,151 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.about-page {
|
||||
.top-bar-wrapper {
|
||||
background: 0 0;
|
||||
.top-bar {
|
||||
background: 0 0;
|
||||
padding: 1.5rem 0;
|
||||
}
|
||||
|
||||
.top-bar-section ul{
|
||||
li, li a {
|
||||
background: 0 0;
|
||||
}
|
||||
|
||||
li a:hover {
|
||||
background: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1.275rem;
|
||||
}
|
||||
|
||||
.intro {
|
||||
//background-color: #7A7A7A;
|
||||
background: image-url('intro-bg.jpg') no-repeat bottom center scroll;
|
||||
background-size: cover;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: table;
|
||||
|
||||
.intro-heading {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
|
||||
.heading, .sub-heading {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sub-heading {
|
||||
margin-top: 2rem;
|
||||
p {
|
||||
line-height: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.circle {
|
||||
color: #fff;
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
font-size: 3rem;
|
||||
border: 2px solid #eee;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
padding: 0.5rem 0;
|
||||
margin-top: 2rem;
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#about {
|
||||
background-color: #000;
|
||||
color: #eee;
|
||||
padding: 10rem 0;
|
||||
h1, h2 {
|
||||
color: #eee;
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
#work {
|
||||
background: image-url('download-bg.jpg') no-repeat bottom center scroll;
|
||||
background-size: cover;
|
||||
padding: 10rem 0;
|
||||
h1, h2 {
|
||||
color: #eee;
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #eee;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
#contact {
|
||||
background: #000;
|
||||
background-size: cover;
|
||||
padding: 10rem 0;
|
||||
padding-bottom: 20rem;
|
||||
h1, h2 {
|
||||
color: #eee;
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #eee;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mail_to {
|
||||
margin-bottom: 3rem;
|
||||
margin-top: -1rem;
|
||||
}
|
||||
|
||||
.contact-ul {
|
||||
text-align: center;
|
||||
li {
|
||||
display: inline-block;
|
||||
}
|
||||
li a {
|
||||
display: inline-block;
|
||||
padding: 0.5rem 2rem;
|
||||
border: 1px solid #219AB3;
|
||||
border-radius: 0.5rem;
|
||||
color: #219AB3;
|
||||
margin: 0 1rem;
|
||||
transition: all .3s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
outline: 0;
|
||||
color: #000;
|
||||
background-color: #219ab3;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 0.5rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
i.douban {
|
||||
font-style: normal;
|
||||
font-size: 95%;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1190,3 +1190,4 @@ $base-font-size: 100%;
|
|||
|
||||
@import 'foundation';
|
||||
@import 'foundation-icons';
|
||||
@import 'font-awesome';
|
||||
|
|
|
@ -1,5 +1,67 @@
|
|||
- content_for(:title) do
|
||||
| 关于我
|
||||
.row
|
||||
.small-12.large-9.large-centered.columns.self-introduce
|
||||
= render 'common/aboutme'
|
||||
- content_for(:main) do
|
||||
/! 导航
|
||||
.about-page ng-app='app' ng-controller='AboutScrollController'
|
||||
.top-bar-wrapper.contain-to-grid.fixed
|
||||
.row
|
||||
.small-12.columns
|
||||
nav.top-bar data-topbar='' role='navigation'
|
||||
ul.title-area
|
||||
li.name
|
||||
h1
|
||||
a href='/' WinDy's Blog
|
||||
section.top-bar-section
|
||||
ul.right
|
||||
li
|
||||
a href='#about' du-smooth-scroll='' du-scrollspy='' 关于
|
||||
li
|
||||
a href='#work' du-smooth-scroll='' du-scrollspy='' 作品
|
||||
li
|
||||
a href='#contact' du-smooth-scroll='' du-scrollspy='' 联系
|
||||
header.intro
|
||||
.intro-heading
|
||||
.row
|
||||
.small-12.columns
|
||||
h1.heading 李亚飞
|
||||
.sub-heading
|
||||
p
|
||||
| 懒, 是人类进步的动力
|
||||
br
|
||||
| 所谓技术, 就是让你的生活越来越懒
|
||||
a.circle href='#about' du-smooth-scroll=''
|
||||
i.fa.fa-angle-double-down
|
||||
section#about
|
||||
.row
|
||||
.small-12.large-9.large-centered.columns
|
||||
h1.title 关于我
|
||||
p Grayscale is a free Bootstrap 3 theme created by Start Bootstrap. It can be yours right now, simply download the template on the preview page. The theme is open source, and you can use it for any purpose, personal or commercial.
|
||||
p Grayscale is a free Bootstrap 3 theme created by Start Bootstrap. It can be yours right now, simply download the template on the preview page. The theme is open source, and you can use it for any purpose, personal or commercial.
|
||||
p Grayscale is a free Bootstrap 3 theme created by Start Bootstrap. It can be yours right now, simply download the template on the preview page. The theme is open source, and you can use it for any purpose, personal or commercial.
|
||||
section#work
|
||||
.row
|
||||
.small-12.large-9.large-centered.columns
|
||||
h1.title 作品
|
||||
p Grayscale is a free Bootstrap 3 theme created by Start Bootstrap. It can be yours right now, simply download the template on the preview page. The theme is open source, and you can use it for any purpose, personal or commercial.
|
||||
p Grayscale is a free Bootstrap 3 theme created by Start Bootstrap. It can be yours right now, simply download the template on the preview page. The theme is open source, and you can use it for any purpose, personal or commercial.
|
||||
p Grayscale is a free Bootstrap 3 theme created by Start Bootstrap. It can be yours right now, simply download the template on the preview page. The theme is open source, and you can use it for any purpose, personal or commercial.
|
||||
section#contact
|
||||
.row
|
||||
.small-12.large-9.large-centered.columns
|
||||
h1.title 联系我
|
||||
p.mail_to
|
||||
= mail_to 'lyfi2003@gmail.com'
|
||||
ul.contact-ul
|
||||
li
|
||||
a href='https://github.com/windy' target='_blank'
|
||||
i.fa.fa-github
|
||||
| Github
|
||||
li
|
||||
a href='http://www.douban.com/people/41759170/' target='_blank'
|
||||
i.douban
|
||||
| 豆
|
||||
| Douban
|
||||
li
|
||||
a href='http://www.linkedin.com/pub/yafei-lee/77/3b/505' target='_blank'
|
||||
i.fa.fa-linkedin-square
|
||||
| LinkedIn
|
||||
|
|
|
@ -13,53 +13,56 @@ html
|
|||
/ 增加 favico 图标
|
||||
link href="/favicon.png" type='image/png' rel="icon"
|
||||
body
|
||||
.off-canvas-wrap data-offcanvas=''
|
||||
.inner-wrap
|
||||
nav.tab-bar
|
||||
section.left-small
|
||||
a.left-off-canvas-toggle.menu-icon href="#"
|
||||
span
|
||||
h1.title.middle-text
|
||||
= link_to ENV['SITE_NAME'], root_path
|
||||
aslide.left-off-canvas-menu
|
||||
ul.off-canvas-list
|
||||
li
|
||||
label Menu
|
||||
li
|
||||
= link_to root_path do
|
||||
i.fi-home
|
||||
| 首页
|
||||
li
|
||||
= link_to '/tech' do
|
||||
i.fi-social-evernote
|
||||
| 技术
|
||||
li
|
||||
= link_to '/life' do
|
||||
i.fi-torsos-male-female
|
||||
| 生活
|
||||
li
|
||||
= link_to '/creator' do
|
||||
i.fi-lightbulb
|
||||
| 创业
|
||||
li
|
||||
label Archive
|
||||
li
|
||||
= link_to archives_path do
|
||||
i.fi-align-justify
|
||||
| 时间线
|
||||
li
|
||||
label About
|
||||
= link_to about_path do
|
||||
i.fi-torso
|
||||
| 关于我
|
||||
section.main-section ng-app="app"
|
||||
- flash.each do |name, msg|
|
||||
- if msg.is_a?(String)
|
||||
div class=("alert-box #{name == :notice ? "success" : "alert"}") data-alert=""
|
||||
= content_tag :div, msg
|
||||
a.close href="#" ×
|
||||
= yield
|
||||
= render "layouts/footer"
|
||||
a.exit-off-canvas
|
||||
- if content_for?(:main)
|
||||
= yield(:main)
|
||||
- else
|
||||
.off-canvas-wrap data-offcanvas=''
|
||||
.inner-wrap
|
||||
nav.tab-bar
|
||||
section.left-small
|
||||
a.left-off-canvas-toggle.menu-icon href="#"
|
||||
span
|
||||
h1.title.middle-text
|
||||
= link_to ENV['SITE_NAME'], root_path
|
||||
aslide.left-off-canvas-menu
|
||||
ul.off-canvas-list
|
||||
li
|
||||
label Menu
|
||||
li
|
||||
= link_to root_path do
|
||||
i.fi-home
|
||||
| 首页
|
||||
li
|
||||
= link_to '/tech' do
|
||||
i.fi-social-evernote
|
||||
| 技术
|
||||
li
|
||||
= link_to '/life' do
|
||||
i.fi-torsos-male-female
|
||||
| 生活
|
||||
li
|
||||
= link_to '/creator' do
|
||||
i.fi-lightbulb
|
||||
| 创业
|
||||
li
|
||||
label Archive
|
||||
li
|
||||
= link_to archives_path do
|
||||
i.fi-align-justify
|
||||
| 时间线
|
||||
li
|
||||
label About
|
||||
= link_to about_path do
|
||||
i.fi-torso
|
||||
| 关于我
|
||||
section.main-section ng-app="app"
|
||||
- flash.each do |name, msg|
|
||||
- if msg.is_a?(String)
|
||||
div class=("alert-box #{name == :notice ? "success" : "alert"}") data-alert=""
|
||||
= content_tag :div, msg
|
||||
a.close href="#" ×
|
||||
= yield
|
||||
= render "layouts/footer"
|
||||
a.exit-off-canvas
|
||||
|
||||
= render 'layouts/google_analytics'
|
||||
|
|
Loading…
Reference in New Issue