原生JS在指定div制作一个文件夹管理器,实现新增,删除文件夹等功能(上篇)

如何在指定div制作一个文件夹管理器

实现效果:

文件夹管理器

一、核心文件准备

js文件
文件名作用
tool.js用来获取选择的元素
data.js存储文件夹数据
createHtml.js页面创建
feature.js1. 选择相关函数 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,由于太久了找不到原作者就不@了
希望本文对你有所帮助

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
javascript写的windows资源管理器<br>解压运行scripting.html,在IE6.0中打开(不能单独打开view.html这是一个子页面,必须由父页面调用)即可。<br>首发地址为51aspx<br>该源码在www.51aspx.com发布<br>本javascript程序是我自己利用业余时间做的,主要是编写javascript进一步对其进行控制。<br>因为时间的关系只提供了局部份功能,还有很多代码和函数都没有进行优化,(注释也较少)比如错误处理,浏览器嗅探等。<br>这里需要说明的是很少用到了innerHTML和innerTEXT两个方法,这是微软提供的专利方法,还没有得到W3C的认可,<br>在别的浏览器里面这两个方法不一定会被支持。<br>所以很多地方是用了DOM的方式进行处理。<br>首次的功能有:<br>1.查看磁盘,显示磁盘各种信息,显示磁盘占用率(图片)。<br>2.查看文件夹文件,运行文件。<br>功能不是最重要的,本功能在windows资源管理器都能轻易做到,相信没人用这个做资源管理器吧,呵呵~~<br>主要是为了让javascript,DOM,CSS良好的呈现一种网页组织,真正的使<br>“结构”,“行为”,“样式”三者在(x)html里面完全分离开来。<br>着重使用了DOM模型编程。<br>javascript方面主要就是程序设计与功能实现,主要还是用到了Scripting组件。<br>CSS就随便写了一点,反正2个页面,不过用的都是常用的一些属性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值