react学习札记(三)--自己的日历控件

4 篇文章 0 订阅
3 篇文章 0 订阅

最近项目因需要一个个性化的日历,用react写了一个日历控件,如图所示

(function(global){
	flag = 0;
	var choice;
	var Calendar = function(div, date, datemoney){
		this.div = document.getElementById(div);
		var w = document.documentElement.clientWidth;
		var h = document.documentElement.clientHeight;
		this.width = w; 
		this.height = h*3/5;
		this.date = date;
		this.div.style.width = this.width + 'px'; //按默认值设置回去
		this.div.style.height = this.height + 'px';//按默认值设置回去
		this.datemoney = datemoney;
		document.getElementById('header_date').innerHTML = this.date.getFullYear() + '年' + (this.date.getMonth() + 1) + '月';
	};

	Calendar.prototype['showUI'] = function(){
		var exist = document.getElementById('day_table');
		for(var i = 0; i < 42; i++){
	   	    var aim = document.getElementById('day'+i);
	   	    if (aim!=null && 1 == aim.getAttribute('flag'))
	   	    	choice = aim.getAttribute('date');
	  	}
	  	//alert(choice);
		if(!!exist){
			this.div.removeChild(exist);
		}
		
		var width = this.width,
		    height = this.height,
		    cell = {width: width/7, height: (height -30 - 20)/6},
		    monthArr = this._monthPanel(this.date);
		this.div.style.cursor = 'default';
		this.div.style.fontFamily = '微软雅黑';
		var CurDate = new Date();
		var month = CurDate.getMonth()+1;
		var day = CurDate.getDate();
		var today;
		if(month>=10 && day >=10)
			today = CurDate.getFullYear()+"/"+month+"/"+day;
		else if(month>=10 && day <10)
		    today = CurDate.getFullYear()+"/"+month+"/0"+day;
		else if(month<10 && day >= 10)
			today = CurDate.getFullYear()+"/0"+month+"/"+day;
		else
			today = CurDate.getFullYear()+"/0"+month+"/0"+day;
		var tableDOM = document.createElement('table');
		tableDOM.id = "day_table";
		//生成日历表格框架,通过monthArr向其中复制
		for(var i=0;i<42;i++){
			var attr_date;
			var attr_month = monthArr.date[i].getMonth()+1;
			var attr_day = monthArr.date[i].getDate();
			if(attr_month>=10 && attr_day >=10)
				attr_date = monthArr.date[i].getFullYear()+"/"+attr_month+"/"+attr_day;
			else if(attr_month>=10 && attr_day <10)
			    attr_date = monthArr.date[i].getFullYear()+"/"+attr_month+"/0"+attr_day;
			else if(attr_month<10 && attr_day >= 10)
				attr_date = monthArr.date[i].getFullYear()+"/0"+attr_month+"/"+attr_day;
			else
				attr_date = monthArr.date[i].getFullYear()+"/0"+attr_month+"/0"+attr_day;
			if (i%7 == 0){
				var trDOM = document.createElement('tr');
				trDOM.id = "week"+parseInt(i/7);
				var tdDOM = document.createElement('td');
				var cellDOM	= document.createElement('div');
				cellDOM.style.width = cell.width + 'px';
				cellDOM.style.height = cell.height + 'px';
				cellDOM.setAttribute('flag',"0");
				cellDOM.setAttribute('date',attr_date); 
				var pDOM = document.createElement('p');
				if(cellDOM.getAttribute('date') == today){
					pDOM.innerHTML = monthArr.date[i].getDate()+"今日";
					pDOM.id = "now";
				}else
					pDOM.innerHTML = monthArr.date[i].getDate();
				pDOM.style.marginTop = parseInt(cell.width/7)+'px';
				//pDOM.style.marginBottom = '0';
				cellDOM.appendChild(pDOM);
				cellDOM.className = 'day';
				cellDOM.id = 'day' + i;
				tdDOM.appendChild(cellDOM);
				trDOM.appendChild(tdDOM);
				tableDOM.appendChild(trDOM);
			}
			else{
				var tdDOM = document.createElement('td');
				var cellDOM	= document.createElement('div');
				cellDOM.style.width = cell.width + 'px';
				cellDOM.style.height = cell.height + 'px';
				cellDOM.setAttribute('flag',"0");
				cellDOM.setAttribute('date',attr_date); 
				//cellDOM.setAttribute('disabled','disabled');
				var pDOM = document.createElement('p');
				if(cellDOM.getAttribute('date') == today){
					pDOM.innerHTML = monthArr.date[i].getDate()+"今日";
					pDOM.id = "now";
				}else
					pDOM.innerHTML = monthArr.date[i].getDate();
				pDOM.style.marginTop = parseInt(cell.width/7)+'px';
				//pDOM.style.marginBottom = '0';
				cellDOM.appendChild(pDOM);
				cellDOM.className = 'day';
				cellDOM.id = 'day' + i;
				tdDOM.appendChild(cellDOM);
				trDOM.appendChild(tdDOM);
			}
			if(i < monthArr.preLen || i >= monthArr.currentLen + monthArr.preLen){
				cellDOM.style.color = '#BFBFBF';
			}
		}
		this.div.appendChild(tableDOM);
		var date;
		//判断从外部传入的数组,加入日期对应的钱数
		for(var i = 0; i < 42; i++){
	      var aim = document.getElementById('day'+i);
	      //alert(this.datemoney);
	      for(date in this.datemoney){
		      if(aim!=null&&aim.getAttribute("date")==date && date>=today)
		      {
		        //test.style.backgroundColor = "#fedd00";
		        aim.setAttribute("money",this.datemoney[date]);
		        aim.className = "day hasmoney";
		        var money = document.createElement('p');
		        money.className = "money";
		        money.innerHTML = "¥"+this.datemoney[date];
		        aim.appendChild(money);
				//choice.style.border = "2px solid #fedd00";
				if(choice==aim.getAttribute('date')){
					aim.style.border = "2px solid #fedd00";
					aim.setAttribute('flag','1');
				}
		      }
		  }
	    }
	    //点击日期生成票的张数和总钱数
		$(".hasmoney").on("click",function(e){
			var node = e.target;
			if(node.id.indexOf('day') > -1 && node.className.indexOf('hasmoney') > -1){
				//callback(node.getAttribute('date'));
				if(1==node.getAttribute("flag") && flag == 1){
					node.setAttribute('flag',"0");
					node.style.border = "1px solid #C8CACC";
					document.getElementById('number').innerHTML = 0;
					flag = 0;
					document.getElementById('total-money').innerHTML = 0; 
				}
				else if(0==node.getAttribute("flag")&& flag == 0){
					node.setAttribute('flag',"1");
					flag = 1;
					node.style.border = "2px solid #fedd00";
					document.getElementById('number').innerHTML = 1;
					document.getElementById('total-money').innerHTML = node.getAttribute('money');
				}
				if(0 == flag){
					document.getElementById('number').innerHTML = 0;
					document.getElementById('total-money').innerHTML = 0; 
				}
			}
		});
		$(".money").on("click",function(e){
			var node = e.target.parentNode;
			if(node.id.indexOf('day') > -1 && node.className.indexOf('hasmoney') > -1){
				//callback(node.getAttribute('date'));
				if(1==node.getAttribute("flag") && flag == 1){
					node.setAttribute('flag',"0");
					node.style.border = "1px solid #C8CACC";
					document.getElementById('number').innerHTML = 0;
					flag = 0;
					document.getElementById('total-money').innerHTML = 0; 
				}
				else if(0==node.getAttribute("flag")&& flag == 0){
					node.setAttribute('flag',"1");
					flag = 1;
					node.style.border = "2px solid #fedd00";
					document.getElementById('number').innerHTML = 1;
					document.getElementById('total-money').innerHTML = node.getAttribute('money');
				}
				if(0 == flag){
					document.getElementById('number').innerHTML = 0;
					document.getElementById('total-money').innerHTML = 0; 
				}
			}
		});
	};

	Calendar.prototype._monthPanel = function(date){
		//如果传递了Date对象,则按Date对象进行计算月份面板
		//否则,按照当前月份计算面板
		var myDate = date || new Date(),
		    year = myDate.getFullYear(),
		    month = myDate.getMonth(),
		    day = myDate.getDate(),
		    week = myDate.getDay(),
		    currentDays = new Date(year, month + 1, 0).getDate(),
		    preDays = new Date(year, month, 0).getDate(),
		    firstDay = new Date(year, month, 1),
		    firstCell = firstDay.getDay() === 0 ? 6 : firstDay.getDay() - 1,
		    bottomCell =  42 - currentDays - firstCell;
		//前一个月该显示多少天
		var preMonth = [];
		for(var p = firstCell; p > 0; p--){
			preMonth.push(new Date(year, month - 1, preDays - p + 1));
		}
		var len = preMonth.length;
		//本月
		var currentMonth = [];
		for(var c = 0; c < currentDays; c++){
			currentMonth.push(new Date(year, month, c + 1));
		}
		//下一个月
	    var nextMonth = [];
	    for(var n = 0; n < bottomCell; n++){
	    	nextMonth.push(new Date(year, month + 1, n + 1));
	    }

	    preMonth = preMonth.concat(currentMonth, nextMonth);
	    return {
	    	date: preMonth,
	    	preLen: len,
	    	currentLen: currentMonth.length
	    };
	};

	global.Calendar = Calendar;

})(window);

这段js是生成日历主体内容结构的。
Calendar.prototype._monthPanel
这个方法可作为一个api来使用,直接生成当月的天数,以及对应的情况。
var Share = React.createClass({
  componentDidMount: function() {
    var datemoney = new Array();//需要从外部得到的日期价钱对应表
    datemoney["2016/03/01"] = "500";
    datemoney["2016/03/17"] = "1000";
    datemoney["2016/03/25"] = "5400";
    datemoney["2016/04/23"] = "4000";
    datemoney["2016/04/02"] = "4300";
    (function(global){
      //var calendar_codeshow = document.getElementById('calendar_codeshow');
      var CurDate = new Date();
      var year = CurDate.getFullYear();
      var month = CurDate.getMonth()+1;
      var day = CurDate.getDate();
      var arr_date;
      var arr_date_2;
      for(arr_date in datemoney){
        arr_date_2 = arr_date;
        break;
      }
      var date = new Date(arr_date_2);
      //日历
      var calendar = new Calendar('calendar',date,datemoney);//
      calendar.showUI(); 
      $("#pre").on('click',function(e){
        var year = parseInt(date.getFullYear()),
        month = parseInt(date.getMonth());
        if(month == 0){
          date = new Date(year - 1, 11, 1);
        }else{
          date = new Date(year, month - 1, 1);
        }
        calendar = new Calendar('calendar',date,datemoney);//
        calendar.showUI(); 
      });
      $("#next").on('click',function(e){
        var year = parseInt(date.getFullYear()),
        month = parseInt(date.getMonth());
        if(month === 11){
          date = new Date(year + 1, 0, 1);
        }else{
          date = new Date(year, month + 1, 1);
        }
        calendar = new Calendar('calendar',date,datemoney);//
        calendar.showUI(); 
      });
      $('#add').on("click",function(e){
        for(var i=0;i<42;i++){
          var aim = document.getElementById('day'+i);
          if(aim!=null && aim.getAttribute("flag") == 1){
            //alert("if"+1 == flag && 1==aim.getAttribute("flag"));
            //alert("e"+document.getElementById('number').innerHTML);
            var money = parseInt(aim.getAttribute('money'));
            if(1 == flag && 1==aim.getAttribute("flag")){
              document.getElementById('number').innerHTML++;
              //alert(document.getElementById('number').innerHTML);
              var number = parseInt(document.getElementById('number').innerHTML);
              document.getElementById('total-money').innerHTML = money * number;
              //callback(money*number,number);
            }
          }
        }
      });
      $('#reduce').on("click",function(e){
        if(parseInt(document.getElementById('number').innerHTML)>1){
        for(var i=0;i<42;i++){
          var aim = document.getElementById('day'+i);
          if(aim!=null && aim.getAttribute("flag") == 1){
            var money = parseInt(aim.getAttribute('money'));
            document.getElementById('number').innerHTML--;
            var number = parseInt(document.getElementById('number').innerHTML);
            //alert(money);
            document.getElementById('total-money').innerHTML = money * number;
            //callback(money*number,number);
          }
        }}
      });
      $('.submit').on('click',function(e){
        var total_money = document.getElementById('total-money').innerHTML;
        var number = document.getElementById('number').innerHTML;
        alert(total_money);
        alert(number);
      });
    })(this);
  },
  render: function(){
    return (
        <div id="calendar-main">
          <div id="header">
            <p className = "head-content">选择活动出发日期<button><img className="close" src="http://download.duckr.cn/wechat/service/close_btn.png" /></button></p>
          </div>
          <div id="calendar">
            <table id ="week_table">
              <tr>
                <td><div>一</div></td>
                <td><div>二</div></td>
                <td><div>三</div></td>
                <td><div>四</div></td>
                <td><div>五</div></td>
                <td><div>六</div></td>
                <td><div>日</div></td>
              </tr>
            </table>
            <table id = "header_table">
              <tr>
                <td><div id = "pre"><<上月</div></td>
                <td><div id = "header_date"></div></td>
                <td><div id = "next">下月>></div></td>
              </tr>
            </table>
          </div>
          <div id="bottom">
            <div id ="reduce-add">购买数量
              <button className="reduce"><img id="reduce" src="http://download.duckr.cn/wechat/service/minus_ticket.png"/></button>
              <span className="zhang">张</span><span id="number">0</span>
              <button className="add"><img id ="add" src="http://download.duckr.cn/wechat/service/add_ticket.png"/></button>
            </div>
            <button className="submit">支付(¥<span id="total-money">0</span>)</button>
          </div>
        </div>
    );
  } 
});
React.render(React.createElement(Share , null),
     document.getElementById('content'));

这是外部框架的js,也就是在这个js中调用calendar的。

Safari对于js Date函数有一个坑,就是必须用最标准的形式如Date(YYYY/MM/DD),进行初始化,new Date('2011-04-12'.replace(/-/g, "/"))这样就可以。

其他浏览器可以用相对宽松的形式如Date("2012-3-5")这种的都可以解析,很关键!Safari还有很多坑,比如一个在以前提过的,h5media播放器无法自动播放的情况,必须有一个用户的动作才能触发播放。(在safri on ios里面明确指出等待用户的交互动作后才能播放media,也就是说如果你没有得到用户的action就播放的话就会被safri拦截)

Safari在点击事件(onclick)中还有一个坑,需要给你的dom写一个css样式 cursor:pointer,因为safari认为这才是一个可点击区域。但是好像使用jQuery on绑定的点击事件就没有问题。。


最后还有个布局上的收获,如果需要在底部加一个其他颜色的蒙版,像最上面那个灰黑色蒙版,这时候不能用background-color+opacity,因为这样会使它下面所有的子div都是变透明,而应该在外面大div中使用css3中给出的rgba(0,0,0,0.7),前面三个代表颜色,最后一个代表透明度,用这种方法就是只在父div中有透明度。nice!


关于布局中的居中问题,可以参考下面这段话:

让行内元素水平居中显示,我们需要为其父级元素设置text-align:center,一般这个属性是用于将文字水平居中的,我们的行内元素就相当于一行之内的文字了,所以可以使用这个方法。
让块级元素,水平居中的办法是为块元素本身添加margin:0 auto;这样块级元素的左右边距就是自动的,也就可以在是水平方向上居中了。
不管是inline-block还是block,我们需要理解其居中的原理,是inline-block,就对其父级元素添加text-align:center,是块级元素就对其本身添加margin:0 auto;记住了这些,以后再对元素进行居中,居左,居右的时候就不用担心自己不会啦。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值