如何在指定div制作一个文件夹管理器
实现效果:
一、核心文件准备
js文件
文件名 | 作用 |
---|---|
tool.js | 用来获取选择的元素 |
data.js | 存储文件夹数据 |
createHtml.js | 页面创建 |
feature.js | 1. 选择相关函数 2. 弹窗相关函数 3. 文件操作相关函数 |
view.js | 文件功能相关事件 |
链接: css,图片等相关文件点击下载
二、写入代码
1. 在需要显示的div中加入以下代码
<!------------------ 功能按键 ------------------------>
<div class="widget-header feature">
<span class="delete-file" >删除</span>
<span class="new-file" id="createfolder">新建</span>
</div>
<!----------------- 文件夹显示区域 -------------------->
<div class="tab-content"
<div class="main">
<!-- 云盘内容主体区 -->
<div class="container">
<!-- 导航区 -->
<div class="nav">
<div class="catalog">
首页
</div>
</div>
<!--/ 导航区 -->
<!-- 文件内容区 -->
<div class="wrap-file layout-preview" id="file-container" style="left: 0px;">
<!-- 单个文件夹示例 -->
<!--
<div class="file-panel">
<span class="file-checkbox"></span>
<span class="file-rename"></span>
<span class="file-delete"></span>
</div>
<div class="file-img"></div>
<div class="file-info">New File(1)</div>
<input class="file-rename-text" type="text" value="New File(1)">
-->
</div>
<!-- 文件夹内容区 -->
<!--/ 云盘主体区 -->
</div>
<!--/ 页面主体部分 -->
<!-- 弹窗 -->
<div class="alert-box">
<!-- 消息弹窗 -->
<div class="" id="notification"><p></p><span></span></div>
<!--/ 消息弹窗 -->
<!-- 咨询弹窗 -->
<div class="question-shadow">
<div class="question"><strong></strong><p></p><span>确定</span><span>取消</span></div>
</div>
<!--/ 咨询弹窗 -->
<!-- 活动窗 -->
<div class="active-window">
<div>
</div>
</div>
<!--/ 活动窗 -->
<!-- 遮罩层 -->
<div class="shadow"></div>
<!--/ 遮罩层 -->
</div>
</div>
</div>
2. js部分
(1)data.js
此处可更改为从数据库获取数据,具体格式如下:
var user_data = {
maxId: 10,
files: [
{
name: 'Root',
id: 0,
type: 'root',
type:'folder',
time: '2017-01-01',
children: [
{
name: 'Front Frame',
id: 1,
pId: 0,
type:'folder',
time: '2017-10-02',
children: [
{
name: 'React',
id: 4,
pId: 1,
type:'folder',
time: '2017-01-03',
children: []
},
{
name: 'Vue',
id: 5,
pId: 1,
type:'folder',
time: '2017-01-04',
children: [
{
name: 'vue-cli',
id: 6,
pId: 5,
type:'folder',
time: '2017-01-04',
children: []
}
]
}
]
},
{
name: 'HTML5',
id: 2,
pId: 0,
type:'folder',
time: '2017-01-01',
children: []
},
{
name: 'CSS3',
id: 3,
pId: 0,
type:'folder',
time: '2017-05-01',
children:[]
},
{
name : 'WebDeveloper',
id : 7,
pId : 0,
type : 'image',
src : 'img/data-image/WebDeveloper.gif',
width: 800,
height :533,
time : '2017-03-28',
children :[]
},
{
name : 'WorkHard',
id : 8,
pId : 0,
type : 'image',
src : 'img/data-image/WorkHard.jpg',
width: 1000,
height :714,
time : '2017-06-01',
children :[]
},
{
name : 'BookNotes',
id : 9,
pId : 0,
type : 'note',
time : '2017-04-28',
children :[]
}
]
}
]
};
3. createHtml.js
将数据渲染
到页面,然后生成数据目录便于返回上一级文件
功能的实现
// 获取全局公用元素
var wrapFiles = tool.$('#file-container'); //文件内容区
var arrFile = wrapFiles.children; //文件内容区的 子元素集合
var allChecked = tool.$('.all-in'); //全选框
// -------------------------------------------------------------
//获取数据
var data = user_data.files; //数据 根目录
var currentData = data[0].children; //当前页面显示的文件的数据(初始化为根目录)
var currentDataId = 0; //当前数据的Id
// -------------------------------------------------------------
console.log(currentData);
//初始化页面
function initHtml() {
wrapFiles.innerHTML = createFileHtml(currentData);
addFileEvent();
catalogEvent();
}
initHtml();
//创建文件内容区的HTML结构
function createFileHtml(data) {
var str = ``,
i, len = data.length;
for (var i = 0; i < len; i++) {
str += `<div class="file" data-id="${data[i].id}">
<div class="file-panel">
<span class="file-checkbox"></span>
<span class="file-delete"></span>
<span class="file-rename"></span>
</div>
<div class="file-img ${'file-type-' + data[i].type}"></div>
<div class="file-info" title="${data[i].name}">${data[i].name}</div>
<input class="file-rename-text" type="text" value="${data[i].name}" spellcheck="false">
<time class="file-time">${data[i].time}</time>
</div>`
}
return str;
}
// 遍历当前页面显示的所有文件夹
function addFileEvent() {
Array.from(arrFile).forEach(function(item) {
var itemPanel = tool.$('.file-panel', item);
item.onmouseover = function() {
itemPanel.style.opacity = '1';
}
item.onmouseout = function() {
itemPanel.style.opacity = '';
}
});
}
//生成目录结构
function catalogEvent() {
var catalog = tool.$('.catalog'); //目录栏
var arrCatalog = tool.$('a', catalog);
for (var i = 0; i < arrCatalog.length; i++) {
arrCatalog[i].index = i;
arrCatalog[i].onclick = function() {
fileClick(arrCatalog[this.index].dataset.id);
var fileClickId = arrCatalog[this.index].dataset.id * 1;
if (!fileClickId) {
catalog.innerHTML = 'Root';
}
}
}
}
// 通过id获取对应数据
function getItemDataById(data, id) {
var current = null,
i, len = data.length;
for (var i = 0; i < len; i++) {
if (data[i].id === id) {
current = data[i];
break;
}
if (!current && data[i].children.length) {
current = getItemDataById(data[i].children, id);
if (current) break;
}
}
return current;
}
// 通过id获取对应祖先数据
function getParentsById(data, id) {
if (typeof id === 'undefined') return;
var arr = [];
var current = getItemDataById(data, id);
arr.push(current);
arr = arr.concat(getParentsById(data, current.pId));
return arr;
}
// 通过id获取对应子孙数据
function getChildrenById(data, id){
if (typeof id === 'undefined') return;
var arr = [];
var current = getItemDataById(data, id);
arr.push(current);
var currentChildren = current.children;
if (current.children.length) {
for (var i = 0; i < currentChildren.length; i++) {
if (currentChildren[i].children) {
arr = arr.concat(getChildrenById(data,currentChildren[i].id));
}
}
}
return arr;
}
3. feature.js
点击文件夹或者图片实现打开文件夹或者显示图片
// ---------------------------------------
//移除当前文档的选中状态
function removeFileChecked() {
allChecked.classList.remove('active');
for (var i = 0; i < currentData.length; i++) {
currentData[i].checked = false;
}
}
//进入文件夹功能函数(显示当前数据某个子元素的子集)------------------------------------------------------------------------------------------
function fileClick(dataId) {
dataId = dataId * 1;
//去除未进入文件夹时的数据选中
removeFileChecked();
var catalog = tool.$('.catalog'); //目录栏
currentData = getItemDataById(data, dataId).children;
var str = ``,
currentParentId; //当前数据的pId
var arrAncestor = getParentsById(data, dataId);
currentDataId = arrAncestor[0].id;
//当前页面显示数据的父级pId
if (!arrAncestor[1]) {
currentParentId = 0;
} else {
currentParentId = arrAncestor[1].id;
}
str = `<a class="to-parent" href="javascript:;" data-id="${currentParentId}">Previous</a>
<span>|</span>`;
//生成目录栏数据
for (var i = arrAncestor.length - 2; i >= 0; i--) {
str += `<a class="${arrAncestor[i].name}" href="javascript:;" data-id="${arrAncestor[i].id}">${arrAncestor[i].name}</a>`;
if (i) str += `<span>></span>`;
}
catalog.innerHTML = str;
initHtml();
}
//遮罩层函数
function shadow(onOff) {
var shadowBox = tool.$('.shadow'),
main = tool.$('.main');
if (onOff) {
main.classList.add('blur');
shadowBox.style.transform = 'scale(1)';
} else {
main.classList.remove('blur');
shadowBox.style.transform = '';
}
}
function fileImage(fileId) {
shadow(true);
var dataImage = getItemDataById(currentData, fileId),
wrapImage = tool.$('.img-box');
wrapImage.src = dataImage.src;
tool.css(wrapImage, {
width: dataImage.width,
height: dataImage.height
});
wrapImage.style.left = window.innerWidth / 2 - dataImage.width / 2 + 'px';
wrapImage.style.top = window.innerHeight / 2 - dataImage.height / 2 + 'px';
tool.animate(wrapImage, {
scale: 1
}, 100);
wrapImage.addEventListener('click', function() {
shadow(false);
tool.animate(wrapImage, {
scale: 0
}, 50);
})
}
4. view.js
处理各种相关事件的功能,比如点击文件夹,通过此处来跳转到相对应的功能函数
// -----------------------------------------------------------------------------------------------
//点击文件的相关事件
wrapFiles.addEventListener('click', function(e) {
var target = e.target,
targetCls = target.classList;
//获取点击的文件节点以及他的ID
var fileGrandparent = target.parentNode.parentNode,
fileId = fileGrandparent.dataset.id * 1;
//文件勾选功能------------------------------------------------------
if (targetCls.contains('file-checkbox')) {
var dataChecked = getItemDataById(data, fileId),
onOff = !dataChecked.checked;
changeCheckedbox(fileGrandparent, target, dataChecked, onOff);
eventAllChecked();
}
//重命名功能--------------------------------------------------------
if (targetCls.contains('file-rename')) {
fileRename(fileId,fileGrandparent);
}
//删除文件功能----------------------------------------------------------
if (targetCls.contains('file-delete')) {
fileDeleteUnchecked(fileId);
}
//进入文件夹----------------------------------------------------------
if (targetCls.contains('file-img')) {
fileId = target.parentNode.dataset.id * 1;
var fileType = getItemDataById(currentData,fileId).type;
if ( fileType === 'folder') {
fileClick(fileId);
}
if (fileType === 'image') {
fileImage(fileId);
}
}
//点击文件名重命名------------------------------------------------------
if (targetCls.contains('file-info')) {
var timerRename = setTimeout(function(){
fileRename(target.parentNode.dataset.id*1,target.parentNode);
},400);
}
});
以上js文件可按需求更改代码,tool文件固定即可
5. tool.js
/**
* 用来获取选择的元素
*/
var tool = {};
// 元素选择器
tool.$ = function (selector, context){
var context = context || document;
var first = selector.substr(0, 1);
var len = selector.split(' ').length; // join
var eles;
// 如果是id选择器
// console.log(first === '#' && len === 1);
if(first === '#' && len === 1){
return document.getElementById(selector.substr(1));
}
// 如果是CSS选择器
eles = context.querySelectorAll(selector);
return eles.length === 1 ? eles[0] : Array.from(eles);
}
/**
* 获取或者设置一个DOM元素的innerHTML
*/
tool.html = function html(ele, val){
if(typeof val === 'undefined'){
return ele.innerHTML;
}
ele.innerHTML = val;
}
/**
* 获取或者设置一个元素的value
*/
tool.val = function val(ele, value){
if(typeof value === 'undefined'){
return ele.value;
}
ele.value = value;
}
// 判断某个元素是否有某个class
tool.hasClass = function (ele, cls){
return ele.classList.contains(cls);
};
// 给某个元素添加一个class
tool.addClass = function (ele, cls){
ele.classList.add(cls);
};
// 给某个元素删除某个class
tool.rmClass = function (ele, cls){
ele.classList.remove(cls);
};
// 给某个元素toggle某个class
tool.toggleClass = function (ele, cls){
ele.classList.toggle(cls);
};
/**
* 用来获取和设置元素的css样式
*/
tool.css = function css(){
var args = arguments, ele = args[0], type = args[1], value = args[2], len = args.length, ret, _this = this;
if(len === 2){
if(type === ''){
ele.style.cssText = '';
return true;
}
if(typeof type === 'string'){
if(getTransform(type)){
return this.cssTransform(ele, type);
}
ret = getComputedStyle(ele)[type];
if(getStyle(type)){
return parseFloat(ret);
};
return ret * 1 ? ret * 1 : ret;
}
if(typeof type === 'object'){
for(var key in type){
setStyle(key, type[key]);
}
return true;
}
}
if(len === 3){
setStyle(type, value);
}
function setStyle(attr, value){
if(getStyle(attr) && typeof value === 'string'){
ele.style[attr] = value;
}else if(getStyle(attr)){
ele.style[attr] = parseFloat(value) + 'px';
}else if(getTransform(attr)){
_this.cssTransform(ele, attr, value);
}else{
ele.style[attr] = value;
}
}
function getStyle(type){
return type === 'width' || type === 'height'|| type === 'left' || type === 'top' || type === 'right' || type === 'bottom';
}
function getTransform(type){
return type === 'translateX' || type === 'translateY'|| type === 'rotate' || type === 'rotateX' || type === 'rotateY' || type === 'scale' || type === 'scaleX' || type === 'scaleY' || type === 'skewX' || type === 'skewY' || type === 'translate' || type === 'skew';
}
}
// 必须通过这个函数设置的才能通过这个函数获取
tool.cssTransform = function cssTransform(ele, type, value){
var attrs = ele.__transform = ele.__transform || {}, str = '';
if(typeof value === 'undefined'){
return attrs[type];
}
attrs[type] = value;
for(var key in attrs){
switch(key){
case 'translateX':
case 'translateY':
str += ` ${key}(${parseFloat(attrs[key])}px)`;
break;
case 'rotate':
case 'rotateX':
case 'rotateY':
case 'skewX':
case 'skewY':
str += ` ${key}(${parseFloat(attrs[key])}deg)`;
break;
default:
str += ` ${key}(${attrs[key]})`;
}
}
ele.style.transform = str.trim();
}
// 动画函数
tool.animate = function animate(ele, attrs, duration, fx, fn){
if(typeof duration === 'undefined'){
duration = 500;
fx = 'linear';
}
if(typeof duration === 'number'){
if(typeof fx === 'function'){
fn = fx;
fx = 'linear';
}
if(typeof fx === 'undefined'){
fx = 'linear';
}
}
if(typeof duration === 'function'){
fn = duration;
fx = 'linear';
duration = 500;
}
if(typeof duration === 'string'){
if(typeof fx === 'undefined'){
fx = duration;
duration = 500;
}else{
fn = fx;
fx = duration;
duration = 500;
}
}
var beginValue = {}, changeValue = {};
for(var key in attrs){
beginValue[key] = this.css(ele, key) || 0;
changeValue[key] = attrs[key] - beginValue[key];
}
var d = duration;
var startTime = Date.now();
var current, c, b, t, _this = this;
window.cancelAnimationFrame(ele.animate);
(function animate(){
ele.animate = window.requestAnimationFrame(animate, ele);
t = Date.now() - startTime;
if(t >= d){
t = d;
window.cancelAnimationFrame(ele.animate);
ele.animate = null;
}
for(key in changeValue){
c = changeValue[key];
b = beginValue[key];
current = Tween[fx](t, b, c, d);
_this.css(ele, key, current);
}
if(!ele.animate && typeof fn === 'function'){
fn.call(ele);
}
})();
};
//抖函数
tool.shake = function shake(ele, attr, nums, fn){
if(ele.shake) return;
var arr = [], index = 0, _this = this;
for(var i=nums < 10 ? 10 : nums; i>=0; i--){
if(i == 0){
arr.push(i);
break;
}
arr.push(-i, i);
}
(function shake(){
ele.shake = window.requestAnimationFrame(shake, ele);
_this.css(ele, attr, arr[index++]);
if(index === arr.length) {
window.cancelAnimationFrame(ele.shake);
ele.shake = null;
if(typeof fn === 'function'){
fn.call(ele);
}
}
})();
}
var Tween = {
linear: function (t, b, c, d){ //匀速
return c*t/d + b;
},
easeIn: function(t, b, c, d){ //加速曲线
return c*(t/=d)*t + b;
},
easeOut: function(t, b, c, d){ //减速曲线
return -c *(t/=d)*(t-2) + b;
},
easeBoth: function(t, b, c, d){ //加速减速曲线
if ((t/=d/2) < 1) {
return c/2*t*t + b;
}
return -c/2 * ((--t)*(t-2) - 1) + b;
},
easeInStrong: function(t, b, c, d){ //加加速曲线
return c*(t/=d)*t*t*t + b;
},
easeOutStrong: function(t, b, c, d){ //减减速曲线
return -c * ((t=t/d-1)*t*t*t - 1) + b;
},
easeBothStrong: function(t, b, c, d){ //加加速减减速曲线
if ((t/=d/2) < 1) {
return c/2*t*t*t*t + b;
}
return -c/2 * ((t-=2)*t*t*t - 2) + b;
},
elasticIn: function(t, b, c, d, a, p){ //正弦衰减曲线(弹动渐入)
if (t === 0) {
return b;
}
if ( (t /= d) == 1 ) {
return b+c;
}
if (!p) {
p=d*0.3;
}
if (!a || a < Math.abs(c)) {
a = c;
var s = p/4;
} else {
var s = p/(2*Math.PI) * Math.asin (c/a);
}
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
},
elasticOut: function(t, b, c, d, a, p){ //*正弦增强曲线(弹动渐出)
if (t === 0) {
return b;
}
if ( (t /= d) == 1 ) {
return b+c;
}
if (!p) {
p=d*0.3;
}
if (!a || a < Math.abs(c)) {
a = c;
var s = p / 4;
} else {
var s = p/(2*Math.PI) * Math.asin (c/a);
}
return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
},
elasticBoth: function(t, b, c, d, a, p){
if (t === 0) {
return b;
}
if ( (t /= d/2) == 2 ) {
return b+c;
}
if (!p) {
p = d*(0.3*1.5);
}
if ( !a || a < Math.abs(c) ) {
a = c;
var s = p/4;
}
else {
var s = p/(2*Math.PI) * Math.asin (c/a);
}
if (t < 1) {
return - 0.5*(a*Math.pow(2,10*(t-=1)) *
Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
}
return a*Math.pow(2,-10*(t-=1)) *
Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b;
},
backIn: function(t, b, c, d, s){ //回退加速(回退渐入)
if (typeof s == 'undefined') {
s = 1.70158;
}
return c*(t/=d)*t*((s+1)*t - s) + b;
},
backOut: function(t, b, c, d, s){
if (typeof s == 'undefined') {
s = 3.70158; //回缩的距离
}
return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
},
backBoth: function(t, b, c, d, s){
if (typeof s == 'undefined') {
s = 1.70158;
}
if ((t /= d/2 ) < 1) {
return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
}
return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
},
bounceIn: function(t, b, c, d){ //弹球减振(弹球渐出)
return c - Tween['bounceOut'](d-t, 0, c, d) + b;
},
bounceOut: function(t, b, c, d){//*
if ((t/=d) < (1/2.75)) {
return c*(7.5625*t*t) + b;
} else if (t < (2/2.75)) {
return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b;
} else if (t < (2.5/2.75)) {
return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b;
}
return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b;
},
bounceBoth: function(t, b, c, d){
if (t < d/2) {
return Tween['bounceIn'](t*2, 0, c, d) * 0.5 + b;
}
return Tween['bounceOut'](t*2-d, 0, c, d) * 0.5 + c*0.5 + b;
}
}
以上仅提供js核心技术,部分删除新增文件夹等功能请查看下篇文章
本文技术参考于github,由于太久了找不到原作者就不@了
希望本文对你有所帮助