<commit_before>global.$ = $;

(function(undefined){

var ls = localStorage;
var jp = JSON.parse;
var js = JSON.stringify;

var server = require("server");
var PHost = server.PHost;

//init data
var hostId = ls["hostId"] ? ls["hostId"] : "1";
var hostHash = ls["hostHash"] ? ls["hostHash"] : js({ "0":"单击", "1": "双击" });
var hostNamePrefix = "PHost-";

ls[hostNamePrefix + "base-host"] = '#提交bug: https://github.com/paper/PHost/issues'+
									'\r\n#说明：这个是基础 host。也就是说，即使你切换不同的host，都会包含这个里面的内容。';

ls[hostNamePrefix + "0"] = "#单击：查看对应的host内容";
ls[hostNamePrefix + "1"] = "#双击：把对应的host设置为系统host";

$(function(){

  var $baseHostBtn = $("#J-base-host");
  var $addHostBtn = $("#J-add-host-btn");

  var $hostArea = $("#J-host-area");

  var $pop = $(".pop");
  var $popCloseBtn = $(".pop .close-btn");
  var $lightbox = $("#J-lightbox");

  var $popAddHost = $("#J-pop-add-host");
  var $popAddHostNameInput = $("#J-add-host-name");
  var $popAddHostBtn = $popAddHost.find(".pop-content .btn");

  var $popDelHost = $("#J-pop-del-host");
  var $popDelHostName = $popDelHost.find(".pop-content .q strong");
  var $popDelCancelBtn = $popDelHost.find(".pop-content .btn-cancel");
  var $popDelOkBtn = $popDelHost.find(".pop-content .btn-warning");

  var $nodeList = $("#J-node-list");
  var $nodeListWrap = $nodeList.find("ul");
  var $nodeListAllLinks = $nodeList.find("a");

	//提示
	var $tip = $("#J-tip");
	var $tipContent = $tip.find("p");
	var tipTime = null;
	var tipStayTime = 1000;

	//写host
	var hostAreaChangeTime = null;
	var hostAreaChangeInterval = 200;

  function showLightbox(){ $lightbox.fadeIn("fast"); }
  function hideLightbox(){ $lightbox.fadeOut("fast"); }

	function getHostId(){
		hostId = (+hostId) + 1;
		ls["hostId"] = hostId;

		return hostId + "";
	}

	var hostContentOp = {
		get : function(id){
			return ls[hostNamePrefix + id];
		},

		set : function(id, data){
      //if window
      data = data.replace(/([^\r])(\n)/g,"$1\r\n");

			ls[hostNamePrefix + id] = data;
		},

		clear : function(id){
			this.set(id, "");
	  }
	}

	//hostHash 相关操作
	var hostHashOp = {
		get : function(){
			return jp( hostHash );
		},

		set : function(id, title){
			var obj = jp( hostHash );
			obj[id] = title;
			//updata
			var objStr = js( obj );
			ls["hostHash"] = objStr;
			hostHash = objStr;

			return obj;
		},

		del : function(id){
			var obj = jp( hostHash );

			if( typeof obj[id] != "undefined" ){
				delete obj[id];
				//updata
				var objStr = js( obj );
				ls["hostHash"] = objStr;
				hostHash = objStr;

				hostContentOp.clear(id);
			}

			return obj;
		}

	}//end hostHashOp

	var popOp = {
		hide : function(){
			$pop.fadeOut("fast");
			hideLightbox();
		},

		showAddHost : function(callback){
			showLightbox();
			$popAddHost.fadeIn("fast");
			//reset
			$popAddHostNameInput
			.attr("placeholder", "添加新的Host")
			.val("")
			.focus();

			callback && callback($popAddHostNameInput, $popAddHostBtn);
		},

		showDelHost : function(callback){
			showLightbox();
			$popDelHost.fadeIn("fast");
			$popDelHostName.html(''); //reset

			callback && callback($popDelHostName, $popDelOkBtn);
		},

		shake : function(){
			$pop.addClass("pop-shake");
			setTimeout(function(){ $pop.removeClass("pop-shake"); }, 500);
		}
	}

  function getNodeListItemHtml(id, title){
		var exData = 'data-id="'+id+'" data-title="'+title+'"';
		var nodeItemId = 'J-node-item-'+ id;

		var nodeItemHtml = '
'+
								''+
									'
'+ title +'
'+
									'
'+
										''+
										''+
									'
'+
									'
'+
										''+
									'
'+
								''+
							'
';

		return nodeItemHtml;
  }

	//如果用户输入的host名字太长，那么就要添加title属性
	function checkLongTitle($nodeItem){
		var $hostTitle = $nodeItem.find(".host-title");
		var $titleWord = $nodeItem.find(".host-title span");

		var titleWidth = $titleWord.width();

		if( titleWidth > 200 ){
			$hostTitle.attr("title", $titleWord.html());
		}else{
			$hostTitle.removeAttr("title");
		}
	}

	//添加一个host
	function addHost(id, title){

		//if addHost(title)
		if( arguments.length == 1 ){
			title = id;
			id = getHostId();
		}

		title = PHost.filterXss(title);

		hostHashOp.set(id, title);

		if( hostContentOp.get(id) === undefined ){
			hostContentOp.set(id, '# host 请写这里:\n');
		}

		var nodeItemHtml = getNodeListItemHtml(id, title);
		$nodeListWrap.prepend(nodeItemHtml);

		var $curNodeItem = $("#J-node-item-" + id);
		checkLongTitle( $curNodeItem );

		return $curNodeItem;
	}

	function getParentNodeItemData($self){
		var $nodeItem =$self.parents(".node-item");
    var id = $nodeItem.attr("data-id");
    var title = $nodeItem.attr("data-title");

		return {
			$nodeItem : $nodeItem,
			id : id,
			title : title
		}
	}

	function writeHostIntoSys(data){
		var d = hostContentOp.get("base-host") + "\r\n\r\n" + data;
		PHost.setSysHost( d );
		return d;
	}

	function keyboardEnter( factorFunc, callback ){

		//if keyboardEnter(callback)
		if( arguments.length == 1 ){
			 callback = factorFunc;
			 factorFunc = function(){ return true };
		}

		document.onkeyup = function(ev){
			if( factorFunc() === true && ev.keyCode == 13 ){
				callback && callback();
			}
		}

	}

	//显示提示
	function showTip(msg){
		clearTimeout(tipTime);

		msg = msg || "操作成功";

		$tipContent.html(msg);
		$tip.show();

		tipTime = setTimeout(function(){
			$tip.hide();
		}, tipStayTime);
	}

	//------------------------------------- event --------------------------------------

  $popCloseBtn.on("click", function(){ popOp.hide(); });
  $popDelCancelBtn.on("click", function(){ popOp.hide(); });

	//基础host（父） 点击
  $baseHostBtn.on("click", function(){
    $hostArea.val( hostContentOp.get("base-host") );

		$(".side .node-item a").removeClass("node-item-click");
		$(this).addClass("node-item-click");

		var nodeItemData = getParentNodeItemData($baseHostBtn);
    var id = nodeItemData.id;
    var title = nodeItemData.title;

		$hostArea.attr({
			"data-id" : id,
			"data-title" : title,
			"data-writeSys" : 0
		});
  });

	//添加新的host
  $addHostBtn.on("click", function(ev){
    popOp.showAddHost(function($input, $btn){

			function okBtnAction(){
				var newTitle = $.trim( $input.val() );

        if( newTitle == "" ){
          popOp.shake();
          $input.focus();
          return;
        }

				$curNodeItem = addHost(newTitle);
				checkLongTitle($curNodeItem);

				popOp.hide();
			}

			keyboardEnter(function(){
				return document.activeElement.id == "J-add-host-name";
			}, function(){
				console.log(111);
				okBtnAction();
			});

      $btn[0].onclick = function(){
				okBtnAction();
      }

    });
  });

	//修改host名称
  $nodeList.on("click", ".op-edit", function(ev){
    ev.stopPropagation();

    var $self = $(this);
		var nodeItemData = getParentNodeItemData($self);
		var $nodeItem = nodeItemData.$nodeItem;
    var id = nodeItemData.id;
    var title = nodeItemData.title;

    popOp.showAddHost(function($input, $btn){
      $input.val(title).select();
      $input.attr("placeholder", "想把 \""+ title +"\" 修改成？");

			function okBtnAction(){
				var newTitle = $.trim( $input.val() );

        //如果没有修改name
        if( newTitle == title ) { popOp.hide(); return; }

        if( newTitle == "" ){
          popOp.shake();
          $input.focus();
          return;
        }

				newTitle = PHost.filterXss(newTitle);

				$nodeItem.attr("data-title", newTitle);
				var $hostTitle = $nodeItem.find(".host-title span");
				$hostTitle.html(newTitle);

				checkLongTitle($nodeItem);

				hostHashOp.set(id, newTitle);

				popOp.hide();
			}

			keyboardEnter(function(){
				return document.activeElement.id == "J-add-host-name";
			}, function(){
				okBtnAction();
			});

      $btn[0].onclick = function(){
        okBtnAction();
      }

    });
  });//end op-edit

	//删除 host
  $nodeList.on("click", ".op-del", function(ev){
    ev.stopPropagation();

    var $self = $(this);
    var nodeItemData = getParentNodeItemData($self);
		var $nodeItem = nodeItemData.$nodeItem;
    var id = nodeItemData.id;
    var title = nodeItemData.title;

    popOp.showDelHost(function($hostName, $btn){
      $hostName.html(title);

      $btn[0].onclick = function(){
				hostHashOp.del(id);
				$nodeItem.remove();

				popOp.hide();
      }

    });
  });//end op-del

	//host列表点击
  $nodeList.on("click", "a", function(){
    var $self = $(this);

		var nodeItemData = getParentNodeItemData($self);
    var id = nodeItemData.id;
    var title = nodeItemData.title;

    $(".side .node-item a").removeClass("node-item-click");
    $(this).addClass("node-item-click");

		$hostArea.val( hostContentOp.get(id) );

		$hostArea.attr({
			"data-id" : id,
			"data-title" : title,
			"data-writeSys" : 0
		});

  });//end nodeList a

	//host列表双击
  $nodeList.on("dblclick", "a", function(){
    var $self = $(this);

    var nodeItemData = getParentNodeItemData($self);
    var id = nodeItemData.id;
    var title = nodeItemData.title;

    $(".side .node-item a").removeClass("node-item-dblclick");
    $(this).addClass("node-item-dblclick");

    PHost.setSysHost(  writeHostIntoSys(hostContentOp.get(id)) );

		//showTip();

		$hostArea.attr({
			"data-id" : id,
			"data-title" : title,
			"data-writeSys" : 1
		});
  });//end nodeList a

	//写host
	$hostArea.keyup(function(){
		clearTimeout(hostAreaChangeTime);

		hostAreaChangeTime = setTimeout(function(){
			var id = $hostArea.attr("data-id");
			var title = $hostArea.attr("data-title");
			var writeSys = +$hostArea.attr("data-writeSys");

			var data = $hostArea.val();

			hostContentOp.set(id, data);

			if( writeSys == 1 ){
				writeHostIntoSys(data);
			}
		}, hostAreaChangeInterval);
	});

  //页面初始化
  function PHostInit(){
		console.log( js(hostHash) );
		var hostHashObj = hostHashOp.get();

		for(var key in hostHashObj){
			var id = key;
			var title = hostHashObj[key];

			addHost(id, title);
		}
  }

  PHostInit();

});

})();
<commit_msg>0.1.1<commit_after>global.$ = $;

(function(undefined){

var ls = localStorage;
var jp = JSON.parse;
var js = JSON.stringify;

var server = require("server");
var PHost = server.PHost;

//init data
var hostId = ls["hostId"] ? ls["hostId"] : "1";
var hostHash = ls["hostHash"] ? ls["hostHash"] : js({ "0":"单击", "1": "双击" });
var hostNamePrefix = "PHost-";

ls[hostNamePrefix + "base-host"] = '#提交bug: https://github.com/paper/PHost/issues'+
									'\r\n#说明：这个是基础 host。也就是说，即使你切换不同的host，都会包含这个里面的内容。';

ls[hostNamePrefix + "0"] = "#单击：查看对应的host内容";
ls[hostNamePrefix + "1"] = "#双击：把对应的host设置为系统host";

$(function(){

  var $baseHostBtn = $("#J-base-host");
  var $addHostBtn = $("#J-add-host-btn");

  var $hostArea = $("#J-host-area");

  var $pop = $(".pop");
  var $popCloseBtn = $(".pop .close-btn");
  var $lightbox = $("#J-lightbox");

  var $popAddHost = $("#J-pop-add-host");
  var $popAddHostNameInput = $("#J-add-host-name");
  var $popAddHostBtn = $popAddHost.find(".pop-content .btn");

  var $popDelHost = $("#J-pop-del-host");
  var $popDelHostName = $popDelHost.find(".pop-content .q strong");
  var $popDelCancelBtn = $popDelHost.find(".pop-content .btn-cancel");
  var $popDelOkBtn = $popDelHost.find(".pop-content .btn-warning");

  var $nodeList = $("#J-node-list");
  var $nodeListWrap = $nodeList.find("ul");
  var $nodeListAllLinks = $nodeList.find("a");

	//提示
	var $tip = $("#J-tip");
	var $tipContent = $tip.find("p");
	var tipTime = null;
	var tipStayTime = 1000;

	//写host
	var hostAreaChangeTime = null;
	var hostAreaChangeInterval = 200;

  function showLightbox(){ $lightbox.fadeIn("fast"); }
  function hideLightbox(){ $lightbox.fadeOut("fast"); }

	function getHostId(){
		hostId = (+hostId) + 1;
		ls["hostId"] = hostId;

		return hostId + "";
	}

	var hostContentOp = {
		get : function(id){
			return ls[hostNamePrefix + id];
		},

		set : function(id, data){
      //if window
      data = data.replace(/([^\r])(\n)/g,"$1\r\n");

			ls[hostNamePrefix + id] = data;
		},

		clear : function(id){
			this.set(id, "");
	  }
	}

	//hostHash 相关操作
	var hostHashOp = {
		get : function(){
			return jp( hostHash );
		},

		set : function(id, title){
			var obj = jp( hostHash );
			obj[id] = title;
			//updata
			var objStr = js( obj );
			ls["hostHash"] = objStr;
			hostHash = objStr;

			return obj;
		},

		del : function(id){
			var obj = jp( hostHash );

			if( typeof obj[id] != "undefined" ){
				delete obj[id];
				//updata
				var objStr = js( obj );
				ls["hostHash"] = objStr;
				hostHash = objStr;

				hostContentOp.clear(id);
			}

			return obj;
		}

	}//end hostHashOp

	var popOp = {
		hide : function(){
			$pop.fadeOut("fast");
			hideLightbox();
		},

		showAddHost : function(callback){
			showLightbox();
			$popAddHost.fadeIn("fast");
			//reset
			$popAddHostNameInput
			.attr("placeholder", "添加新的Host")
			.val("")
			.focus();

			callback && callback($popAddHostNameInput, $popAddHostBtn);
		},

		showDelHost : function(callback){
			showLightbox();
			$popDelHost.fadeIn("fast");
			$popDelHostName.html(''); //reset

			callback && callback($popDelHostName, $popDelOkBtn);
		},

		shake : function(){
			$pop.addClass("pop-shake");
			setTimeout(function(){ $pop.removeClass("pop-shake"); }, 500);
		}
	}

  function getNodeListItemHtml(id, title){
		var exData = 'data-id="'+id+'" data-title="'+title+'"';
		var nodeItemId = 'J-node-item-'+ id;

		var nodeItemHtml = '
'+
								''+
									'
'+ title +'
'+
									'
'+
										''+
										''+
									'
'+
									'
'+
										''+
									'
'+
								''+
							'
';

		return nodeItemHtml;
  }

	//如果用户输入的host名字太长，那么就要添加title属性
	function checkLongTitle($nodeItem){
		var $hostTitle = $nodeItem.find(".host-title");
		var $titleWord = $nodeItem.find(".host-title span");

		var titleWidth = $titleWord.width();

		if( titleWidth > 200 ){
			$hostTitle.attr("title", $titleWord.html());
		}else{
			$hostTitle.removeAttr("title");
		}
	}

	//添加一个host
	function addHost(id, title){

		//if addHost(title)
		if( arguments.length == 1 ){
			title = id;
			id = getHostId();
		}

		title = PHost.filterXss(title);

		hostHashOp.set(id, title);

		if( hostContentOp.get(id) === undefined ){
			hostContentOp.set(id, '# host 请写这里:\n');
		}

		var nodeItemHtml = getNodeListItemHtml(id, title);
		$nodeListWrap.prepend(nodeItemHtml);

		var $curNodeItem = $("#J-node-item-" + id);
		checkLongTitle( $curNodeItem );

		return $curNodeItem;
	}

	function getParentNodeItemData($self){
		var $nodeItem =$self.parents(".node-item");
    var id = $nodeItem.attr("data-id");
    var title = $nodeItem.attr("data-title");

		return {
			$nodeItem : $nodeItem,
			id : id,
			title : title
		}
	}

	function writeHostIntoSys(data){
		var d = hostContentOp.get("base-host") + "\r\n\r\n" + data;
		PHost.setSysHost( d );
		return d;
	}

	function keyboardEnter( factorFunc, callback ){

		//if keyboardEnter(callback)
		if( arguments.length == 1 ){
			 callback = factorFunc;
			 factorFunc = function(){ return true };
		}

		document.onkeyup = function(ev){
			if( factorFunc() === true && ev.keyCode == 13 ){
				callback && callback();
			}
		}

	}

	//显示提示
	function showTip(msg){
		clearTimeout(tipTime);

		msg = msg || "操作成功";

		$tipContent.html(msg);
		$tip.show();

		tipTime = setTimeout(function(){
			$tip.hide();
		}, tipStayTime);
	}

	//------------------------------------- event --------------------------------------

  $popCloseBtn.on("click", function(){ popOp.hide(); });
  $popDelCancelBtn.on("click", function(){ popOp.hide(); });

	//基础host（父） 点击
  $baseHostBtn.on("click", function(){
    $hostArea.val( hostContentOp.get("base-host") );

		$(".side .node-item a").removeClass("node-item-click");
		$(this).addClass("node-item-click");

		var nodeItemData = getParentNodeItemData($baseHostBtn);
    var id = nodeItemData.id;
    var title = nodeItemData.title;

		$hostArea.attr({
			"data-id" : id,
			"data-title" : title,
			"data-writeSys" : 0
		});
  });

	//添加新的host
  $addHostBtn.on("click", function(ev){
    popOp.showAddHost(function($input, $btn){

			function okBtnAction(){
				var newTitle = $.trim( $input.val() );

        if( newTitle == "" ){
          popOp.shake();
          $input.focus();
          return;
        }

				$curNodeItem = addHost(newTitle);
				checkLongTitle($curNodeItem);

				popOp.hide();
			}

			keyboardEnter(function(){
				return document.activeElement.id == "J-add-host-name";
			}, function(){
				okBtnAction();
			});

      $btn[0].onclick = function(){
				okBtnAction();
      }

    });
  });

	//修改host名称
  $nodeList.on("click", ".op-edit", function(ev){
    ev.stopPropagation();

    var $self = $(this);
		var nodeItemData = getParentNodeItemData($self);
		var $nodeItem = nodeItemData.$nodeItem;
    var id = nodeItemData.id;
    var title = nodeItemData.title;

    popOp.showAddHost(function($input, $btn){
      $input.val(title).select();
      $input.attr("placeholder", "想把 \""+ title +"\" 修改成？");

			function okBtnAction(){
				var newTitle = $.trim( $input.val() );

        //如果没有修改name
        if( newTitle == title ) { popOp.hide(); return; }

        if( newTitle == "" ){
          popOp.shake();
          $input.focus();
          return;
        }

				newTitle = PHost.filterXss(newTitle);

				$nodeItem.attr("data-title", newTitle);
				var $hostTitle = $nodeItem.find(".host-title span");
				$hostTitle.html(newTitle);

				checkLongTitle($nodeItem);

				hostHashOp.set(id, newTitle);

				popOp.hide();
			}

			keyboardEnter(function(){
				return document.activeElement.id == "J-add-host-name";
			}, function(){
				okBtnAction();
			});

      $btn[0].onclick = function(){
        okBtnAction();
      }

    });
  });//end op-edit

	//删除 host
  $nodeList.on("click", ".op-del", function(ev){
    ev.stopPropagation();

    var $self = $(this);
    var nodeItemData = getParentNodeItemData($self);
		var $nodeItem = nodeItemData.$nodeItem;
    var id = nodeItemData.id;
    var title = nodeItemData.title;

    popOp.showDelHost(function($hostName, $btn){
      $hostName.html(title);

      $btn[0].onclick = function(){
				hostHashOp.del(id);
				$nodeItem.remove();

				popOp.hide();
      }

    });
  });//end op-del

	//host列表点击
  $nodeList.on("click", "a", function(){
    var $self = $(this);

		var nodeItemData = getParentNodeItemData($self);
    var id = nodeItemData.id;
    var title = nodeItemData.title;

    $(".side .node-item a").removeClass("node-item-click");
    $(this).addClass("node-item-click");

		$hostArea.val( hostContentOp.get(id) );

		$hostArea.attr({
			"data-id" : id,
			"data-title" : title,
			"data-writeSys" : 0
		});

  });//end nodeList a

	//host列表双击
  $nodeList.on("dblclick", "a", function(){
    var $self = $(this);

    var nodeItemData = getParentNodeItemData($self);
    var id = nodeItemData.id;
    var title = nodeItemData.title;

    $(".side .node-item a").removeClass("node-item-dblclick");
    $(this).addClass("node-item-dblclick");

    PHost.setSysHost(  writeHostIntoSys(hostContentOp.get(id)) );

		//showTip();

		$hostArea.attr({
			"data-id" : id,
			"data-title" : title,
			"data-writeSys" : 1
		});
  });//end nodeList a

	//写host
	$hostArea.keyup(function(){
		clearTimeout(hostAreaChangeTime);

		hostAreaChangeTime = setTimeout(function(){
			var id = $hostArea.attr("data-id");
			var title = $hostArea.attr("data-title");
			var writeSys = +$hostArea.attr("data-writeSys");

			var data = $hostArea.val();

			hostContentOp.set(id, data);

			if( writeSys == 1 ){
				writeHostIntoSys(data);
			}
		}, hostAreaChangeInterval);
	});

  //页面初始化
  function PHostInit(){
		var hostHashObj = hostHashOp.get();

		for(var key in hostHashObj){
			var id = key;
			var title = hostHashObj[key];

			addHost(id, title);
		}
  }

  PHostInit();

});

})();
<|endoftext|>


<commit_before>$(document).ready(function() {

	var page = 1;
	var data;

	if (typeof pagination !== 'undefined') {
		if (pagination === true) {
			$(".pagination").css("display", "block");
		}
	}

	if (typeof top_active !== 'undefined') {
		$("nav a." + top_active).addClass("active");
	}

	if (typeof channel !== 'undefined') {
		if (channel != 'company' && channel != 'engineering') {
			$(".subheader a.category").removeClass("active");
			$(".subheader a.category#" + channel).addClass("active");
		}
	}

	if ($("div.pagination").length > 0) {
		check_page();
	} else {
		$(".posts").css("visibility", "visible");
	}

	if (typeof slug !== 'undefined') {
		if (slug.length > 0 && $(".disqus").length > 0) {
			$.getJSON(prefix + "/json/comments" + slug + ".json", function(response) {
				if (response) {
					comments = response.response
					for (key in comments) {
						comment = comments[key];
						var html = '
';
							html += '';
							html += '
';
								html += '
';
									html += '';
									html += '
';
									if (comment.author_url !== null) html += '';
									html += comment.author_name;
									if (comment.author_url !== null) html += '';
									html += '
';
									html += '
' + comment.date + '
'
								html += '
';
							html += '
';
							html += '
' + comment.message + '
';
						html += '
';
						$(".disqus").prepend(html);
					}
					$(".disqus").prepend("
" + comments.length + " archived comments
");
				}
			})
		}
	}

	function check_page() {
		var href = window.location.hash;
		var matched = href.match('^#page');
		if (matched) {
			var page_num = href.split("#page")[1];
			if (page_num = parseInt(page_num)) {
				page = page_num;
			}
		}
		console.log(prefix + "/json/index.json");
		$.getJSON(prefix + "/json/index.json", function(response) {
			console.log(response)
			if (response) {
				var result = [];
				for (key in response.posts) {
					var post = response.posts[key];
					if (post.draft) continue;
					if (typeof channel !== 'undefined') {
						if (post.tags.indexOf(channel) == - 1) {
							continue;
						}
					}
					if (typeof top_active !== 'undefined' && (top_active == "engineering" || top_active == "company")) {
						if (post.tags.indexOf(top_active) == - 1) {
							continue;
						}
					}
					if (typeof author_id !== 'undefined') {
						if (post.author != author_id) {
							continue;
						}
					}
					result.push(post);
				}
				response.posts = result;

				data = response;

				console.log(response);

				set_page(page);

				// Set total pages
				$("span.page.total_pages").html(Math.max(Math.ceil(data.posts.length / 5), 1));

				// Bind page clicks
				$("a.page").click(function() {
					var selected_page = ($(this).hasClass("older") ? page + 1 : page - 1);
					if (valid_page(selected_page)) {
						set_page(selected_page);
					}
				});

				$(window).hashchange(function() {
					var selected_page = parseInt(window.location.hash.substr(5));
					if (valid_page(selected_page)) {
						set_page(selected_page);
					}
				})
			}
		});
	}

	function set_page(page_num) {
		var max = Math.ceil(data.posts.length / 5);

		if (data == null) return;
		if (!valid_page(page_num)) {
			if (page_num > max) page_num = max;
		}

		page = page_num;

		if (typeof pagination !== 'undefined' && pagination === true) {
			window.location.hash = "#page" + page_num.toString();
		}

		$(window).scrollTop(0);

		var next = page_num + 1;
		var previous = page_num - 1;

		$("span.page.current_page").html(page_num);

		$("a.page.older").css("visibility", page_num >= max ? "hidden" : "visible");
		$("a.page.newer").css("visibility", page_num <= 1 ? "hidden" : "visible");

		var offset = (page_num - 1) * 5;

		var authors_posted = [];

		for (var i = 0; i < 5; i++) {
			var post = data.posts[offset + i];
			var article = $("article.post:eq(" + i + ")");

			article.css("border-bottom", i == data.posts.length - 1 ? "none" : null);
			if (i >= data.posts.length || typeof post == 'undefined') {
				article.css("display", "none");
				continue;
			}

			var author = data.authors[post.author];

			article.find(".title").html(post.title).attr("href", post.url);
			article.find(".avatar").attr("src", author.avatar);

			var post_info = [];

			post_info.push(post.date);
			post_info.push('By ' + author.name);
			post_info.push('In ' + post.tags.join(", "))

			article.find(".post-info").html(post_info.join(" • "));

			article.find("img.hero").attr("src", post.hero);
			article.find("a.hero_url").attr("href", post.url);

			article.find(".excerpt").html(post.content);
			article.find("a.read-more").attr("href", post.url);
			article.css("display", "block");

			var podcast = (post.tags.indexOf('podcasts') > -1);
			article.find(".podcast-container").css("display", podcast ? "block" : "none");

			var no_background = (podcast || post.hero.length == 0);
			article.find(".hero-container").css("display", no_background ? "none" : "block");

			var auth = $("#authors-container .author-container:eq(" + i + ")");
			if (auth && authors_posted.indexOf(author.twitter) == -1) {
				auth.find(".avatar-link").attr("href", author.url);
				auth.find(".avatar").attr("src", author.avatar);
				auth.find(".name-link").attr("href", author.url).html(author.name);
				auth.find("p.job").html(author.job);
				authors_posted.push(author.twitter);
				auth.css("display", "block");
			} else {
				auth.css("display", "none");
			}
		}

		$(".posts").css("visibility", "visible");
	}

	function valid_page(page_num) {
		return (page_num > 0 && page_num <= Math.max(Math.ceil(data.posts.length / 5), 1))
	}
});<commit_msg>Fix accidental global js variable<commit_after>$(document).ready(function() {

	var page = 1;
	var data;

	if (typeof pagination !== 'undefined') {
		if (pagination === true) {
			$(".pagination").css("display", "block");
		}
	}

	if (typeof top_active !== 'undefined') {
		$("nav a." + top_active).addClass("active");
	}

	if (typeof channel !== 'undefined') {
		if (channel != 'company' && channel != 'engineering') {
			$(".subheader a.category").removeClass("active");
			$(".subheader a.category#" + channel).addClass("active");
		}
	}

	if ($("div.pagination").length > 0) {
		check_page();
	} else {
		$(".posts").css("visibility", "visible");
	}

	if (typeof slug !== 'undefined') {
		if (slug.length > 0 && $(".disqus").length > 0) {
			$.getJSON(prefix + "/json/comments" + slug + ".json", function(response) {
				if (response) {
					var key;
					comments = response.response
					for (key in comments) {
						comment = comments[key];
						var html = '
';
							html += '';
							html += '
';
								html += '
';
									html += '';
									html += '
';
									if (comment.author_url !== null) html += '';
									html += comment.author_name;
									if (comment.author_url !== null) html += '';
									html += '
';
									html += '
' + comment.date + '
'
								html += '
';
							html += '
';
							html += '
' + comment.message + '
';
						html += '
';
						$(".disqus").prepend(html);
					}
					$(".disqus").prepend("
" + comments.length + " archived comments
");
				}
			})
		}
	}

	function check_page() {
		var href = window.location.hash;
		var matched = href.match('^#page');
		if (matched) {
			var page_num = href.split("#page")[1];
			if (page_num = parseInt(page_num)) {
				page = page_num;
			}
		}
		console.log(prefix + "/json/index.json");
		$.getJSON(prefix + "/json/index.json", function(response) {
			console.log(response)
			if (response) {
				var result = [];
				var key;
				for (key in response.posts) {
					var post = response.posts[key];
					if (post.draft) continue;
					if (typeof channel !== 'undefined') {
						if (post.tags.indexOf(channel) == - 1) {
							continue;
						}
					}
					if (typeof top_active !== 'undefined' && (top_active == "engineering" || top_active == "company")) {
						if (post.tags.indexOf(top_active) == - 1) {
							continue;
						}
					}
					if (typeof author_id !== 'undefined') {
						if (post.author != author_id) {
							continue;
						}
					}
					result.push(post);
				}
				response.posts = result;

				data = response;

				console.log(response);

				set_page(page);

				// Set total pages
				$("span.page.total_pages").html(Math.max(Math.ceil(data.posts.length / 5), 1));

				// Bind page clicks
				$("a.page").click(function() {
					var selected_page = ($(this).hasClass("older") ? page + 1 : page - 1);
					if (valid_page(selected_page)) {
						set_page(selected_page);
					}
				});

				$(window).hashchange(function() {
					var selected_page = parseInt(window.location.hash.substr(5));
					if (valid_page(selected_page)) {
						set_page(selected_page);
					}
				})
			}
		});
	}

	function set_page(page_num) {
		var max = Math.ceil(data.posts.length / 5);

		if (data == null) return;
		if (!valid_page(page_num)) {
			if (page_num > max) page_num = max;
		}

		page = page_num;

		if (typeof pagination !== 'undefined' && pagination === true) {
			window.location.hash = "#page" + page_num.toString();
		}

		$(window).scrollTop(0);

		var next = page_num + 1;
		var previous = page_num - 1;

		$("span.page.current_page").html(page_num);

		$("a.page.older").css("visibility", page_num >= max ? "hidden" : "visible");
		$("a.page.newer").css("visibility", page_num <= 1 ? "hidden" : "visible");

		var offset = (page_num - 1) * 5;

		var authors_posted = [];

		for (var i = 0; i < 5; i++) {
			var post = data.posts[offset + i];
			var article = $("article.post:eq(" + i + ")");

			article.css("border-bottom", i == data.posts.length - 1 ? "none" : null);
			if (i >= data.posts.length || typeof post == 'undefined') {
				article.css("display", "none");
				continue;
			}

			var author = data.authors[post.author];

			article.find(".title").html(post.title).attr("href", post.url);
			article.find(".avatar").attr("src", author.avatar);

			var post_info = [];

			post_info.push(post.date);
			post_info.push('By ' + author.name);
			post_info.push('In ' + post.tags.join(", "))

			article.find(".post-info").html(post_info.join(" • "));

			article.find("img.hero").attr("src", post.hero);
			article.find("a.hero_url").attr("href", post.url);

			article.find(".excerpt").html(post.content);
			article.find("a.read-more").attr("href", post.url);
			article.css("display", "block");

			var podcast = (post.tags.indexOf('podcasts') > -1);
			article.find(".podcast-container").css("display", podcast ? "block" : "none");

			var no_background = (podcast || post.hero.length == 0);
			article.find(".hero-container").css("display", no_background ? "none" : "block");

			var auth = $("#authors-container .author-container:eq(" + i + ")");
			if (auth && authors_posted.indexOf(author.twitter) == -1) {
				auth.find(".avatar-link").attr("href", author.url);
				auth.find(".avatar").attr("src", author.avatar);
				auth.find(".name-link").attr("href", author.url).html(author.name);
				auth.find("p.job").html(author.job);
				authors_posted.push(author.twitter);
				auth.css("display", "block");
			} else {
				auth.css("display", "none");
			}
		}

		$(".posts").css("visibility", "visible");
	}

	function valid_page(page_num) {
		return (page_num > 0 && page_num <= Math.max(Math.ceil(data.posts.length / 5), 1))
	}
});<|endoftext|>


<commit_before>/**
 * Perfwatcher jsTree config
 *
 * Javascript
 *
 * LICENSE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Monitoring
 * @author    Cyril Feraudet <cyril@feraudet.com>
 * @copyright 2011 Cyril Feraudet
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link      http://www.perfwatcher.org/
 **/

var view_id = 1;

$(function () {
	// Settings up the tree - using $(selector).jstree(options);
	// All those configuration options are documented at http://www.jstree.com/
	$('#tree').jstree({
	    // the list of plugins to include
	    "plugins" : [ "themes", "json_data", "ui", "crrm", "dnd", "search", "types", "contextmenu" ],
	    // Plugin configuration

	    "themes" : {
		"url" : "css/themes/default/style.css",
		"theme" : "default",
		"dots" : true,
		"icons" : true
	    },

	    // I usually configure the plugin that handles the data first - in this case JSON as it is most common
	    "json_data" : {
			// I chose an ajax enabled tree - again - as this is most common, and maybe a bit more complex
			// All the options are the same as jQuery's except for `data` which CAN (not should) be a function
			"ajax" : {
			// the URL to fetch the data
			    "url" : "action.php?tpl=json_tree",
			    // this function is executed in the instance's scope (this refers to the tree instance)
			    // the parameter is the node being loaded (may be -1, 0, or undefined when loading the root nodes)
			    "data" : function (n) {
				// the result is fed to the AJAX request `data` option
						if (location.hash) {
								var h = location.hash.substr(1).split('_');
								if(h[0] == 'id') {
										h.shift();
										view_id = h[0];
								}
						}
					return {
						"operation" : "get_children",
						"view_id" : view_id,
						"id" : n.attr ? n.attr("id").replace("node_","") : 1
					};
			    },
			    "error" : function (data) {
			    	$('body').html(data.responseText);
			    }
			}
	    },
	    // Configuring the search plugin
	    "search" : {
			// As this has been a common question - async search
			// Same as above - the `ajax` config option is actually jQuery's object (only `data` can be a function)
			"case_insensitive" : true,
			"ajax" : {
		    	"url" : "action.php?tpl=json_tree",
		    	"data" : function (str) {
					return {
			    		"operation" : "search",
						"view_id" : view_id,
			    		"search_str" : str
					};
		    	}
			}
	    },
	    // Using types - most of the time this is an overkill
	    // Still meny people use them - here is how
	    "types" : {
		// I set both options to -2, as I do not need depth and children count checking
		// Those two checks may slow jstree a lot, so use only when needed
		"max_depth" : -2,
		"max_children" : -2,
		// I want only `drive` nodes to be root nodes
		// This will prevent moving or creating any other type as a root node
		"valid_children" : [ "folder" ],
		"types" : {
		    // The default type
		    "default" : {
				// I want this type to have no children (so only leaf nodes)
				// In my case - those are files
				"valid_children" : "none",
				// If we specify an icon for the default type it WILL OVERRIDE the theme icons
				"icon" : { "image" : "img/file-grey.png" }
		    },
		    "default-red" : { "valid_children" : "none", "icon" : { "image" : "img/file-red.png" } },
		    "default-green" : { "valid_children" : "none", "icon" : { "image" : "img/file-green.png" } },
		    // The `folder` type
		    "folder" : {
				// can have files and other folders inside of it, but NOT `drive` nodes
				"valid_children" : [ "default", "default-red", "default-grey", "default-green", "folder" ],
				"icon" : { "image" : "img/folder.png" }
		    },
		    // The `drive` nodes
		    "drive" : {
				// can have files and folders inside, but NOT other `drive` nodes
				"valid_children" : [ "default", "default-red", "default-grey", "default-green", "folder" ],
				"icon" : { "image" : "img/folder.png" },
				// those options prevent the functions with the same name to be used on the `drive` type nodes
				// internally the `before` event is used
				"start_drag" : false,
				"move_node" : false,
				"delete_node" : false,
				"remove" : false
		    }
		}
	    },
	    // For UI & core - the nodes to initially select and open will be overwritten by the cookie plugin

	    // the UI plugin - it handles selecting/deselecting/hovering nodes
	    "ui" : {
		// this makes the node with ID node_4 selected onload
		"initially_select" : [ ]
	    },
	    // the core plugin - not many options here
	    "core" : {
		// just open those two nodes up
		// as this is an AJAX enabled tree, both will be downloaded from the server
		"initially_open" : [ ],
		"strings" : { loading : "Loading ...", new_node : "Untiteled"}
	    },
	    "contextmenu" : {
		"select_node" : false,
		"items" : {
		    "create" : {
			"separator_before"	: false,
			"separator_after"	: true,
			"label"			: "Add",
			"action"		: false,
			"submenu"           	: {
			    "createserver" 	: {
				"separator_before"	: false,
				"separator_after"	: true,
				"label"			: "Server",
				"action"		: function (obj) { this.create(obj); }
			    },
			    "createfolder" 	: {
				"separator_before"	: false,
				"separator_after"	: true,
				"label"			: "Folder",
				"action"		: function (obj) { this.create(obj, "last", { "attr" : { "rel" : "folder" } }); }
			    }
			}
		    }
		}
	    }
	})
	.bind("create.jstree", function (e, data) {
	    $.post(
		"action.php?tpl=json_tree",
		{
		    "operation" : "create_node",
			"view_id" : view_id,
		    "id" : data.rslt.parent.attr("id").replace("node_",""),
		    "position" : data.rslt.position,
		    "title" : data.rslt.name,
		    "type" : data.rslt.obj.attr("rel")
		},
		function (r) {
		    if(r.status) {
			$(data.rslt.obj).attr("id", "node_" + r.id);
		    }
		    else {
			$.jstree.rollback(data.rlbk);
		    }
		}
	    );
	    }).bind("remove.jstree", function (e, data) {
		data.rslt.obj.each(function () {
		    $.ajax({
			async : false,
			type: 'POST',
			url: "action.php?tpl=json_tree",
			data : {
			    "operation" : "remove_node",
				"view_id" : view_id,
			    "id" : this.id.replace("node_","")
			},
			success : function (r) {
			    if(!r.status) {
				data.inst.refresh();
			    }
			}
		    });
		});
	    }).bind("rename.jstree", function (e, data) {
		$.post(
		    "action.php?tpl=json_tree",
		    {
			"operation" : "rename_node",
			"view_id" : view_id,
			"id" : data.rslt.obj.attr("id").replace("node_",""),
			"title" : data.rslt.new_name
		    },
		    function (r) {
			if(!r.status) {
			    $.jstree.rollback(data.rlbk);
			}
		    }
	       );
	}).bind("move_node.jstree", function (e, data) {
	    data.rslt.o.each(function (i) {
		$.ajax({
		    async : false,
		    type: 'POST',
		    url: "action.php?tpl=json_tree",
		    data : {
			"operation" : "move_node",
			"view_id" : view_id,
			"id" : $(this).attr("id").replace("node_",""),
			"ref" : data.rslt.np.attr("id").replace("node_",""),
			"position" : data.rslt.cp + i,
			"title" : data.rslt.name,
			"copy" : data.rslt.cy ? 1 : 0
		    },
		    success : function (r) {
			if(!r.status) {
			    $.jstree.rollback(data.rlbk);
			}
			else {
			    $(data.rslt.oc).attr("id", "node_" + r.id);
			    if(data.rslt.cy && $(data.rslt.oc).children("UL").length) {
					data.inst.refresh(data.inst._get_parent(data.rslt.oc));
			    }
			}
		    }
		});
	    });
	}).bind("select_node.jstree", function (e, data) {
	    select_node(data.rslt.obj.attr("id").replace("node_",""));
		//location.hash = data.rslt.obj.attr("id").replace("node_","");
		var path = $("#tree").jstree("get_path", data.rslt.obj, true);
		var hash = '';
		for (n in path) {
			hash = hash + '_' + path[n].replace('node_', '');
		}
		location.hash = 'id_'+view_id+'_'+hash.substr(1);
	}).bind("loaded.jstree", function (event, data) {
		if (!location.hash) { return; }
		var nodes = location.hash.substr(1).split('_');
		if(nodes[0] == 'id') {
			nodes.shift();
			view_id = nodes[0];
			nodes.shift();
			recurse_open_node(nodes);
		} else if(nodes[0] == 'host') {
			var fullhost = location.hash.substr(6);
			select_node_by_name(fullhost);
			$('#mainSplitter').jqxSplitter('collapseAt', 0);
			treecollapsed = true;
		}
    });

	function recurse_open_node (nodes) {
		var node = nodes.shift();
		if (nodes.length == 0) {
			$('#node_'+node+' a').click();
		} else {
			$('#tree').jstree("open_node", $('#node_'+node), function (event, data) { recurse_open_node (nodes); }, true);
		}
	}
});
<commit_msg>bugfix; added selections to 'add' menu<commit_after>/**
 * Perfwatcher jsTree config
 *
 * Javascript
 *
 * LICENSE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @category  Monitoring
 * @author    Cyril Feraudet <cyril@feraudet.com>
 * @copyright 2011 Cyril Feraudet
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link      http://www.perfwatcher.org/
 **/

var view_id = 1;

$(function () {
	// Settings up the tree - using $(selector).jstree(options);
	// All those configuration options are documented at http://www.jstree.com/
	$('#tree').jstree({
	    // the list of plugins to include
	    "plugins" : [ "themes", "json_data", "ui", "crrm", "dnd", "search", "types", "contextmenu" ],
	    // Plugin configuration

	    "themes" : {
		"url" : "css/themes/default/style.css",
		"theme" : "default",
		"dots" : true,
		"icons" : true
	    },

	    // I usually configure the plugin that handles the data first - in this case JSON as it is most common
	    "json_data" : {
			// I chose an ajax enabled tree - again - as this is most common, and maybe a bit more complex
			// All the options are the same as jQuery's except for `data` which CAN (not should) be a function
			"ajax" : {
			// the URL to fetch the data
			    "url" : "action.php?tpl=json_tree",
			    // this function is executed in the instance's scope (this refers to the tree instance)
			    // the parameter is the node being loaded (may be -1, 0, or undefined when loading the root nodes)
			    "data" : function (n) {
				// the result is fed to the AJAX request `data` option
						if (location.hash) {
								var h = location.hash.substr(1).split('_');
								if(h[0] == 'id') {
										h.shift();
										view_id = h[0];
								}
						}
					return {
						"operation" : "get_children",
						"view_id" : view_id,
						"id" : n.attr ? n.attr("id").replace("node_","") : 1
					};
			    },
			    "error" : function (data) {
			    	$('body').html(data.responseText);
			    }
			}
	    },
	    // Configuring the search plugin
	    "search" : {
			// As this has been a common question - async search
			// Same as above - the `ajax` config option is actually jQuery's object (only `data` can be a function)
			"case_insensitive" : true,
			"ajax" : {
		    	"url" : "action.php?tpl=json_tree",
		    	"data" : function (str) {
					return {
			    		"operation" : "search",
						"view_id" : view_id,
			    		"search_str" : str
					};
		    	}
			}
	    },
	    // Using types - most of the time this is an overkill
	    // Still meny people use them - here is how
	    "types" : {
		// I set both options to -2, as I do not need depth and children count checking
		// Those two checks may slow jstree a lot, so use only when needed
		"max_depth" : -2,
		"max_children" : -2,
		// I want only `drive` nodes to be root nodes
		// This will prevent moving or creating any other type as a root node
		"valid_children" : [ "folder" ],
		"types" : {
		    // The default type
		    "default" : {
				// I want this type to have no children (so only leaf nodes)
				// In my case - those are files
				"valid_children" : "none",
				// If we specify an icon for the default type it WILL OVERRIDE the theme icons
				"icon" : { "image" : "img/file-grey.png" }
		    },
		    "default-red" : { "valid_children" : "none", "icon" : { "image" : "img/file-red.png" } },
		    "default-green" : { "valid_children" : "none", "icon" : { "image" : "img/file-green.png" } },
		    // The `folder` type
		    "folder" : {
				// can have files and other folders inside of it, but NOT `drive` nodes
				"valid_children" : [ "default", "default-red", "default-grey", "default-green", "folder" ],
				"icon" : { "image" : "img/folder.png" }
		    },
		    // The `drive` nodes
		    "drive" : {
				// can have files and folders inside, but NOT other `drive` nodes
				"valid_children" : [ "default", "default-red", "default-grey", "default-green", "folder" ],
				"icon" : { "image" : "img/folder.png" },
				// those options prevent the functions with the same name to be used on the `drive` type nodes
				// internally the `before` event is used
				"start_drag" : false,
				"move_node" : false,
				"delete_node" : false,
				"remove" : false
		    }
		}
	    },
	    // For UI & core - the nodes to initially select and open will be overwritten by the cookie plugin

	    // the UI plugin - it handles selecting/deselecting/hovering nodes
	    "ui" : {
		// this makes the node with ID node_4 selected onload
		"initially_select" : [ ]
	    },
	    // the core plugin - not many options here
	    "core" : {
		// just open those two nodes up
		// as this is an AJAX enabled tree, both will be downloaded from the server
		"initially_open" : [ ],
		"strings" : { loading : "Loading ...", new_node : "Untiteled"}
	    },
	    "contextmenu" : {
		"select_node" : false,
		"items" : {
		    "create" : {
			"separator_before"	: false,
			"separator_after"	: true,
			"label"			: "Add",
			"action"		: false,
			"submenu"           	: {
			    "createserver" 	: {
				"separator_before"	: false,
				"separator_after"	: false,
				"label"			: "Server",
				"action"		: function (obj) { this.create(obj, "last", { "attr" : { "rel" : "default", "pwtype" : "server" } }); }
			    },
			    "createselection" 	: {
				"separator_before"	: false,
				"separator_after"	: true,
				"label"			: "Selection",
				"action"		: function (obj) { this.create(obj, "last", { "attr" : { "rel" : "default", "pwtype" : "selection" } }); }
			    },
			    "createfolder" 	: {
				"separator_before"	: false,
				"separator_after"	: true,
				"label"			: "Folder",
				"action"		: function (obj) { this.create(obj, "last", { "attr" : { "rel" : "folder", "pwtype" : "container" } }); }
			    }
			}
		    }
		}
	    }
	})
	.bind("create.jstree", function (e, data) {
	    $.post(
		"action.php?tpl=json_tree",
		{
		    "operation" : "create_node",
			"view_id" : view_id,
		    "id" : data.rslt.parent.attr("id").replace("node_",""),
		    "position" : data.rslt.position,
		    "title" : data.rslt.name,
		    "pwtype" : data.rslt.obj.attr("pwtype"),
		    "type" : data.rslt.obj.attr("rel")
		},
		function (r) {
		    if(r.status) {
			$(data.rslt.obj).attr("id", "node_" + r.id);
		    }
		    else {
			$.jstree.rollback(data.rlbk);
		    }
		}
	    );
	    }).bind("remove.jstree", function (e, data) {
		data.rslt.obj.each(function () {
		    $.ajax({
			async : false,
			type: 'POST',
			url: "action.php?tpl=json_tree",
			data : {
			    "operation" : "remove_node",
				"view_id" : view_id,
			    "id" : this.id.replace("node_","")
			},
			success : function (r) {
			    if(!r.status) {
				data.inst.refresh();
			    }
			}
		    });
		});
	    }).bind("rename.jstree", function (e, data) {
		$.post(
		    "action.php?tpl=json_tree",
		    {
			"operation" : "rename_node",
			"view_id" : view_id,
			"id" : data.rslt.obj.attr("id").replace("node_",""),
			"title" : data.rslt.new_name
		    },
		    function (r) {
			if(!r.status) {
			    $.jstree.rollback(data.rlbk);
			}
		    }
	       );
	}).bind("move_node.jstree", function (e, data) {
	    data.rslt.o.each(function (i) {
		$.ajax({
		    async : false,
		    type: 'POST',
		    url: "action.php?tpl=json_tree",
		    data : {
			"operation" : "move_node",
			"view_id" : view_id,
			"id" : $(this).attr("id").replace("node_",""),
			"ref" : data.rslt.np.attr("id").replace("node_",""),
			"position" : data.rslt.cp + i,
			"title" : data.rslt.name,
			"copy" : data.rslt.cy ? 1 : 0
		    },
		    success : function (r) {
			if(!r.status) {
			    $.jstree.rollback(data.rlbk);
			}
			else {
			    $(data.rslt.oc).attr("id", "node_" + r.id);
			    if(data.rslt.cy && $(data.rslt.oc).children("UL").length) {
					data.inst.refresh(data.inst._get_parent(data.rslt.oc));
			    }
			}
		    }
		});
	    });
	}).bind("select_node.jstree", function (e, data) {
	    select_node(data.rslt.obj.attr("id").replace("node_",""));
		//location.hash = data.rslt.obj.attr("id").replace("node_","");
		var path = $("#tree").jstree("get_path", data.rslt.obj, true);
		var hash = '';
		for (n in path) {
			hash = hash + '_' + path[n].replace('node_', '');
		}
		location.hash = 'id_'+view_id+'_'+hash.substr(1);
	}).bind("loaded.jstree", function (event, data) {
		if (!location.hash) { return; }
		var nodes = location.hash.substr(1).split('_');
		if(nodes[0] == 'id') {
			nodes.shift();
			view_id = nodes[0];
			nodes.shift();
			recurse_open_node(nodes);
		} else if(nodes[0] == 'host') {
			var fullhost = location.hash.substr(6);
			select_node_by_name(fullhost);
			$('#mainSplitter').jqxSplitter('collapseAt', 0);
			treecollapsed = true;
		}
    });

	function recurse_open_node (nodes) {
		var node = nodes.shift();
		if (nodes.length == 0) {
			$('#node_'+node+' a').click();
		} else {
			$('#tree').jstree("open_node", $('#node_'+node), function (event, data) { recurse_open_node (nodes); }, true);
		}
	}
});
<|endoftext|>


<commit_before>/**
 * AJAX form creation
 * @class cowboy.FormAjax
 * @implements {cowboy.Options}
 */
cowboy.FormAjax = new Class ({
	Implements: cowboy.Options,

	options: {
		invalidFieldMessage: 'Please fill this field',
		redirectDelay: 1000,
		onRequest: function() { return; },
		onSuccess: function(response) { return; },
		onFailure: function() { return; },
		redirect: null
	},

	/**
	 * Create a FormAjax
	 * @constructor
	 * @param  {Element}	form		Form element
	 * @param  {Object}		options		Form options
	 */
	initialize: function(form, options) {
		this.form = form;
		var _this = this;

		this.options = Object.merge(this.options, options);

		// Set Options and overload options by properties in the form
		this.setElementOptions(this.options, form);

		this.form.setProperty('autocomplete', 'off');
		this.form.addEvent('submit', this.submit.bind(this));

		this.form.getElements('.required').each(function(el){
			el.addEvent('focus', _this.focus);
			el.addEvent('blur', _this.blur.bind(_this));
		});

		this.uploadReq = new cowboy.Request({
			onRequest: function() {
				return _this.options.onRequest();
			},

			onSuccess: function(response) {
				return _this.options.onSuccess(JSON.decode(response));
			},

			onFailure: function() {
				return _this.options.onFailure();
			}
		});
	},

	/**
	 * Submit the form
	 * @method submit
	 * @param  {Event}	e	Event that triggers the submit
	 */
	submit: function(e) {
		e.stop();

		this.showErrors();

		if (this.form.getElements('.error').length === 0) {
			this.getFormData();

			this.uploadReq.send({ url: this.form.getProperty('action') });
		}
	},

	/**
	 * Event triggered on input focus
	 * @method focus
	 * @param  {Event}	e	Event when an input is focused
	 */
	focus: function(e){
		if(e.target.hasClass('error')) {
			this.removeClass('error');
			this.erase('placeholder');
		}
	},

	/**
	 * Event triggered on input blur
	 * @method blur
	 * @param  {Event}	e	Event when an input is blured
	 */
	blur: function(e){
		if (e.target.value === '') {
			e.target.setProperty('placeholder',this.options.invalidFieldMessage);
			e.target.addClass('error');
		}
	},

	/**
	 * Show the form errors
	 * @method showErrors
	 */
	showErrors: function() {
		_this = this;
		this.form.getElements('.required').each(function(el) {
			if (el.value === '') {
				el.addClass('error');
				el.setProperty('placeholder',_this.options.invalidFieldMessage);
			}
		});
	},

	/**
	 * Get data to submit
	 * @method getFormData
	 */
	getFormData: function() {
		var _this = this;

		this.form.getElements('input[name]').each(function(el) {
			if (el.getProperty('type') == 'checkbox') {
				if (el.checked === true) {
					_this.uploadReq.append(el.name, el.value);
				}
				else {
					_this.uploadReq.append(el.name, 0);
				}
			}
			else if (el.getProperty('type') == 'radio') {
				if (el.checked === true) {
					_this.uploadReq.append(el.name, el.value);
				}
			}
			else if(el.getProperty('type') == 'file') {
				_this.uploadReq.append(el.name, el.files[0]);
			}
			else {
				_this.uploadReq.append(el.name, el.value);
			}
		});

		this.form.getElements('select[name]').each(function(el){
			_this.uploadReq.append(el.name, el.value);
		});

		this.form.getElements('textarea[name]').each(function(el){
			_this.uploadReq.append(el.name, el.value);
		});
	}
});
<commit_msg>Can take an array as a parameter<commit_after>/**
 * AJAX form creation
 * @class cowboy.FormAjax
 * @implements {cowboy.Options}
 */
cowboy.FormAjax = new Class ({
	Implements: cowboy.Options,

	options: {
		invalidFieldMessage: 'Please fill this field',
		redirectDelay: 1000,
		onRequest: function() { return; },
		onSuccess: function(response) { return; },
		onFailure: function() { return; },
		redirect: null
	},

	/**
	 * Create a FormAjax
	 * @constructor
	 * @param  {Element}	form		Form element
	 * @param  {Object}		options		Form options
	 */
	initialize: function(form, options) {
		var _this = this;
		if (form instanceof HTMLElement) {
			this.form = form;

			this.options = Object.merge(this.options, options);

			// Set Options and overload options by properties in the form
			this.setElementOptions(this.options, form);

			this.form.setProperty('autocomplete', 'off');
			this.form.addEvent('submit', this.submit.bind(this));

			this.form.getElements('.required').each(function(el){
				el.addEvent('focus', _this.focus);
				el.addEvent('blur', _this.blur.bind(_this));
			});

			this.uploadReq = new cowboy.Request({
				onRequest: function() {
					return _this.options.onRequest();
				},

				onSuccess: function(response) {
					return _this.options.onSuccess(JSON.decode(response));
				},

				onFailure: function() {
					return _this.options.onFailure();
				}
			});
		}
		else if (form instanceof Object) {
			for (var i = form.length - 1; i >= 0; i--) {
				new cowboy.FormAjax(form[i], options);
			}
		}
	},

	/**
	 * Submit the form
	 * @method submit
	 * @param  {Event}	e	Event that triggers the submit
	 */
	submit: function(e) {
		e.stop();

		this.showErrors();

		if (this.form.getElements('.error').length === 0) {
			this.getFormData();

			this.uploadReq.send({ url: this.form.getProperty('action') });
		}

		this.uploadReq.reset();
	},

	/**
	 * Event triggered on input focus
	 * @method focus
	 * @param  {Event}	e	Event when an input is focused
	 */
	focus: function(e){
		if(e.target.hasClass('error')) {
			this.removeClass('error');
			this.erase('placeholder');
		}
	},

	/**
	 * Event triggered on input blur
	 * @method blur
	 * @param  {Event}	e	Event when an input is blured
	 */
	blur: function(e){
		if (e.target.value === '') {
			e.target.setProperty('placeholder',this.options.invalidFieldMessage);
			e.target.addClass('error');
		}
	},

	/**
	 * Show the form errors
	 * @method showErrors
	 */
	showErrors: function() {
		_this = this;
		this.form.getElements('.required').each(function(el) {
			if (el.value === '') {
				el.addClass('error');
				el.setProperty('placeholder',_this.options.invalidFieldMessage);
			}
		});
	},

	/**
	 * Get data to submit
	 * @method getFormData
	 */
	getFormData: function() {
		var _this = this;

		this.form.getElements('input[name]').each(function(el) {
			if (el.getProperty('type') == 'checkbox') {
				if (el.checked === true) {
					_this.uploadReq.append(el.name, el.value);
				}
				else {
					_this.uploadReq.append(el.name, 0);
				}
			}
			else if (el.getProperty('type') == 'radio') {
				if (el.checked === true) {
					_this.uploadReq.append(el.name, el.value);
				}
			}
			else if(el.getProperty('type') == 'file') {
				_this.uploadReq.append(el.name, el.files[0]);
			}
			else {
				_this.uploadReq.append(el.name, el.value);
			}
		});

		this.form.getElements('select[name]').each(function(el){
			_this.uploadReq.append(el.name, el.value);
		});

		this.form.getElements('textarea[name]').each(function(el){
			_this.uploadReq.append(el.name, el.value);
		});
	}
});
<|endoftext|>


<commit_before>var Reflux = require('reflux');
var request = require('superagent');

function createActions(resource, methods) {

  var resourceUrl = '/' + resource.name;
  var actionConfig = {};
  var actionChildren = {
    children: ['completed', 'failed']
  };

  if (methods.get) {
    actionConfig.load = actionChildren;
  }
  if (methods.post) {
    actionConfig.create = actionChildren;
  }
  if (methods.put) {
    actionConfig.put = actionChildren;
  }
  if (methods.patch) {
    actionConfig.patch = actionChildren;
  }
  if (methods.delete) {
    actionConfig.delete = actionChildren;
  }
  if (methods.update) {
    actionConfig.update = actionChildren;
  }

  // Implement API calls to other additional defined actions
  // otherActions: [
  // {
  //   name: Required
  //   endpoint: Optional - uses configuration + name if not specified
  //   methods: [ List of Supported methods (get, put, post, etc) ]
  // }, ...
  // ]
  if (methods.otherActions) {
    for (var prop in methods.otherActions) {
      if (methods.otherActions.hasOwnProperty(prop)) {
        actionConfig[prop] = actionChildren;

      }
    }
  }

  var actions = Reflux.createActions(actionConfig);

  function getResourceURL() {
    return resourceUrl;
  }

  function getResourceIDURL(model) {
    return resourceUrl + '/' + model.id;
  }

  if (methods.get) {
    actions.load.preEmit = createAction('get', getResourceURL);
  }

  if (methods.post) {
    actions.create.preEmit = createAction('post', getResourceURL, true);
  }

  if (methods.put) {
    var putFunc = createAction('put', getResourceIDURL, true);
    actions.put.preEmit = putFunc;
    if (methods.update === 'put') {
      actions.update.preEmit = putFunc;
    }
  }

  if (methods.patch) {
    var patchFunc = createAction('patch', getResourceIDURL, true);
    actions.patch.preEmit = patchFunc;
    if (methods.update === 'patch') {
      actions.update.preEmit = patchFunc;
    }
  }

  if (methods.delete) {
    actions.delete.preEmit = createAction('delete', getResourceIDURL, true);
  }
  console.log('Actions: ', actions);
  return actions;

  function createAction(method, getUrl, includeBody) {
    return function preEmit(model) {
      var req = request[method](getUrl(model));
      req.set('Accept', 'application/json');
      req.set('Content-Type', 'application/json');
      if (includeBody) {
        req.send(model.toJSON);
      }
      req.end(getCB(this.failed, this.completed));
    };
  }

}

function getCB(errorFunc, okFunc) {
  return function _cb(error, response) {
    if (error) {
      return errorFunc(error);
    }
    if (response.status >= 400) {
      return errorFunc(null, response);
    }
    return okFunc(response);
  };
}

module.exports = createActions;<commit_msg>Refactor to reuse function for creating actions<commit_after>var Reflux = require('reflux');
var request = require('superagent');

var methodMap = {
  get: 'load',
  post: 'create',
  put: 'put',
  patch: 'patch',
  delete: 'delete',
  update: 'update'
};

var includeBodyMap = {
  'get': false,
  'post': true,
  'patch': true,
  'put': true,
  'delete': false
};

var urlMap = {
  'get': 'base',
  'post': 'base',
  'patch': 'id',
  'put': 'id',
  'delete': 'id'
};

function createActions(obj) {

  var resource = obj.resource;
  var methods = obj.methods;
  var otherActions = obj.otherActions;
  var resourceUrl = '/' + resource.name;
  var actionConfig = {};
  var actionChildren = {
    children: ['completed', 'failed']
  };

  for (var method in methods) {
    if (methods.hasOwnProperty(method)) {
      actionConfig[methodMap[method]] = actionChildren;
    }
  }

  // Add other actions to action config
  otherActions.forEach(function(action) {
    actionConfig[action.name] = actionChildren;
  });

  var actions = Reflux.createActions(actionConfig);
  for (method in methods) {
    if (methods.hasOwnProperty(method) && method !== 'update') {
      actions[methodMap[method]].preEmit = createAction(method, resourceUrl);
    }
  }

  if (methods.update === 'patch') {
    actions.update.preEmit = actions.patch.preEmit;
  } else if (methods.update === 'put') {
    actions.upodate.preEmit = actions.put.preEmit;
  }

  if (methods.get) {
    actions.load.preEmit = createAction('get', resourceUrl);
  }

  if (methods.post) {
    actions.create.preEmit = createAction('post', resourceUrl);
  }

  if (methods.put) {
    var putFunc = createAction('put', resourceUrl);
    actions.put.preEmit = putFunc;
    if (methods.update === 'put') {
      actions.update.preEmit = putFunc;
    }
  }

  if (methods.patch) {
    var patchFunc = createAction('patch', resourceUrl);
    actions.patch.preEmit = patchFunc;
    if (methods.update === 'patch') {
      actions.update.preEmit = patchFunc;
    }
  }

  if (methods.delete) {
    actions.delete.preEmit = createAction('delete', resourceUrl);
  }

  // Implement API calls to other additional defined actions
  // otherActions: [
  // {
  //   name: Required
  //   endpoint: Optional - uses configuration + name if not specified
  //   excludeBody: optional - rare case where a put/post/patch request
  //   has no body
  //   methods: [ List of Supported methods (get, put, post, etc) ]
  // }, ...
  // ]
  if (otherActions) {
    otherActions.forEach(function(action) {
      var url = action.name;
      if (action.endpoint) {
        url = action.endpoint;
      }
      actions[action.name].preEmit = createAction(action.method, url, action.excludeBody);
    });
  }
  return actions;
}

function createAction(method, baseURL, excludeBody) {
  return function preEmit(model) {
    var url;
    if (urlMap[method] === 'base') {
      url = baseURL;
    } else {
      url = baseURL + '/' + model.id;
    }

    var req = request[method](url);
    req.set('Accept', 'application/json');
    req.set('Content-Type', 'application/json');
    if (includeBodyMap[method] && !excludeBody) {
      req.send(model.toJSON);
    }
    req.end(getCB(this.failed, this.completed));
  };
}

function getCB(errorFunc, okFunc) {
  return function _cb(error, response) {
    if (error) {
      return errorFunc(error);
    }
    if (response.status >= 400) {
      return errorFunc(null, response);
    }
    return okFunc(response);
  };
}

module.exports = createActions;<|endoftext|>


<commit_before>//init
var initCjs = (function(w,cjs){
	var def = {
		"scaleMode":"exactFit",//适配模式:exactFit | fixedWidth | noScale | showAll
		"frameRate":60,
		"autoRender":true,
		"autoLoad":true,
		"useLoad":true,
		"loadType":0,//0代表div显示加载，1代表使用canvas绘制loading
		"useSound":true,//是否使用soundjs
		"width":640,//设计图宽高
		"height":1014,
		"url":"images/",
		"debug":false,
		"id":'',
		"xhr":true,//图片是否跨域
		"preload":[],
		"bgColor":"#fff",
		"callback":false,
		'onProgress':false,
		'onComplete':false
	}
	var stage,
		canvas,
		W = window,
		D = document,
		SCREEN_W = W.innerWidth,
		SCREEN_H = W.innerHeight,
		DPR = W.devicePixelRatio || 1,
		CANS_W = SCREEN_W*DPR,
		CANS_H = SCREEN_H*DPR,
		SCALE_X = 1,
		SCALE_Y = 1;
	function init(opts){
		//重设参数
		if(typeof opts == 'object'){
			for(var key in opts){
				def[key] = opts[key];
			}
		}
		//拼接完整资源路径
		def.preload.map(function(item,index){
			if(typeof item == 'object'){
				def.preload[index].src = def.url + item.src;
			}else{
				def.preload[index] = def.url + item;
			}
		});
		//创建舞台和设定样式
		if(!def.id){
			var div = D.createElement("div"),
				body = D.getElementsByTagName("body")[0],
				head = D.getElementsByTagName("head")[0],
				style = D.createElement("style");
			style.innerHTML = "html,body{height:100%}.canvas-wrap{position:relative;width:100%;height:100%;left:0;top:0;}.canvas-wrap canvas{width:100%;height:100%;}";
			div.className = "canvas-wrap";
			canvas = D.createElement("canvas");
			canvas.id = "canvas";
			head.appendChild(style);
			div.appendChild(canvas);
			body.appendChild(div);
		}else{
			if(!D.getElementById(def.id)){
				console.warn("id指定错误,请确认id值是否正确。");
				return false;
			}else{
				canvas = D.getElementById(def.id);
				canvas.setAttribute("style","width: 100%;height: 100%;");
			}
		}
		//适配模式
		canvas.width = CANS_W;
		canvas.height = CANS_H;
		stage = new cjs.Stage(canvas);
		this.stage = stage;
		this.width = def.width;
		this.height = def.height;
		SCALE_X = CANS_W/def.width;
		SCALE_Y = CANS_H/def.height;
		this.scaleX = SCALE_X;
		this.scaleY = SCALE_Y;
		var _scaleX = SCALE_X,
			_scaleY = SCALE_Y;
		switch (def.scaleMode){
			case 'fixedWidth':
				_scaleY = SCALE_X;
				break;
			case 'showAll':
				if(def.width/def.height > SCREEN_W/SCREEN_H){
					_scaleX = SCALE_Y;
				}else{
					_scaleY = SCALE_X;
				}
				break;
			case 'exactFit':
			default:
				break;
		}
		stage.scaleX = _scaleX;
		stage.scaleY = _scaleY;
		//渲染帧率
		function _autoRun(){
			stage.update();
		}
		cjs.Ticker.timingMode = cjs.Ticker.RAF;
		cjs.Ticker.framerate = def.frameRate;
		this.startTick = function(){
			cjs.Ticker.addEventListener('tick',_autoRun);
		}
		this.stopTick = function(){
			cjs.Ticker.removeEventListener('tick',_autoRun);
		}
		//是否自动渲染
		if(def.autoRender){
			this.startTick();
		}
		//加载队列
		if(def.useLoad){
			var queue = new cjs.LoadQueue(!def.xhr);
			this.loader = queue;
			//是否加载soundjs
			if(def.useSound){
				queue.installPlugin(cjs.Sound);
			}
		}
		//资源加载
		this.loading = function(){
			if(def.useLoad){
				queue.on("progress", function(){
					(def.onProgress && typeof def.onProgress == 'function') && def.onProgress(queue.progress);
				},this);
				queue.on("complete", function(){
					(def.onComplete && typeof def.onComplete == 'function') && def.onComplete(queue.progress);
					return true;
				},this);
				queue.loadManifest(def.preload);
			}
		}
		//是否自动加载
		if(def.autoLoad){
			this.loading();
		}
	}
	return init;
})(window,createjs);<commit_msg>修改tick模式<commit_after>//init
var initCjs = (function(w,cjs){
	var def = {
		"scaleMode":"exactFit",//适配模式:exactFit | fixedWidth | noScale | showAll
		"frameRate":60,
		"autoRender":true,
		"autoLoad":true,
		"useLoad":true,
		"loadType":0,//0代表div显示加载，1代表使用canvas绘制loading
		"useSound":true,//是否使用soundjs
		"width":640,//设计图宽高
		"height":1014,
		"url":"images/",
		"debug":false,
		"id":'',
		"xhr":true,//图片是否跨域
		"preload":[],
		"bgColor":"#fff",
		"callback":false,
		'onProgress':false,
		'onComplete':false
	}
	var stage,
		canvas,
		W = window,
		D = document,
		SCREEN_W = W.innerWidth,
		SCREEN_H = W.innerHeight,
		DPR = W.devicePixelRatio || 1,
		CANS_W = SCREEN_W*DPR,
		CANS_H = SCREEN_H*DPR,
		SCALE_X = 1,
		SCALE_Y = 1;
	function init(opts){
		//重设参数
		if(typeof opts == 'object'){
			for(var key in opts){
				def[key] = opts[key];
			}
		}
		//拼接完整资源路径
		def.preload.map(function(item,index){
			if(typeof item == 'object'){
				def.preload[index].src = def.url + item.src;
			}else{
				def.preload[index] = def.url + item;
			}
		});
		//创建舞台和设定样式
		if(!def.id){
			var div = D.createElement("div"),
				body = D.getElementsByTagName("body")[0],
				head = D.getElementsByTagName("head")[0],
				style = D.createElement("style");
			style.innerHTML = "html,body{height:100%}.canvas-wrap{position:relative;width:100%;height:100%;left:0;top:0;}.canvas-wrap canvas{width:100%;height:100%;}";
			div.className = "canvas-wrap";
			canvas = D.createElement("canvas");
			canvas.id = "canvas";
			head.appendChild(style);
			div.appendChild(canvas);
			body.appendChild(div);
		}else{
			if(!D.getElementById(def.id)){
				console.warn("id指定错误,请确认id值是否正确。");
				return false;
			}else{
				canvas = D.getElementById(def.id);
				canvas.setAttribute("style","width: 100%;height: 100%;");
			}
		}
		//适配模式
		canvas.width = CANS_W;
		canvas.height = CANS_H;
		stage = new cjs.Stage(canvas);
		this.stage = stage;
		this.width = def.width;
		this.height = def.height;
		SCALE_X = CANS_W/def.width;
		SCALE_Y = CANS_H/def.height;
		this.scaleX = SCALE_X;
		this.scaleY = SCALE_Y;
		var _scaleX = SCALE_X,
			_scaleY = SCALE_Y;
		switch (def.scaleMode){
			case 'fixedWidth':
				_scaleY = SCALE_X;
				break;
			case 'showAll':
				if(def.width/def.height > SCREEN_W/SCREEN_H){
					_scaleX = SCALE_Y;
				}else{
					_scaleY = SCALE_X;
				}
				break;
			case 'exactFit':
			default:
				break;
		}
		stage.scaleX = _scaleX;
		stage.scaleY = _scaleY;
		//渲染帧率
		function _autoRun(){
			stage.update();
		}
		cjs.Ticker.timingMode = cjs.Ticker.RAF_SYNCHED;
		cjs.Ticker.framerate = def.frameRate;
		this.startTick = function(){
			cjs.Ticker.addEventListener('tick',_autoRun);
		}
		this.stopTick = function(){
			cjs.Ticker.removeEventListener('tick',_autoRun);
		}
		//是否自动渲染
		if(def.autoRender){
			this.startTick();
		}
		//加载队列
		if(def.useLoad){
			var queue = new cjs.LoadQueue(!def.xhr);
			this.loader = queue;
			//是否加载soundjs
			if(def.useSound){
				queue.installPlugin(cjs.Sound);
			}
		}
		//资源加载
		this.loading = function(){
			if(def.useLoad){
				queue.on("progress", function(){
					(def.onProgress && typeof def.onProgress == 'function') && def.onProgress(queue.progress);
				},this);
				queue.on("complete", function(){
					(def.onComplete && typeof def.onComplete == 'function') && def.onComplete(queue.progress);
					return true;
				},this);
				queue.loadManifest(def.preload);
			}
		}
		//是否自动加载
		if(def.autoLoad){
			this.loading();
		}
	}
	return init;
})(window,createjs);<|endoftext|>


<commit_before>//var APSTransport = function(server, callback, options){
APS.transport = function(server, callback, client){
	this.state = 0;//0 = Not initialized, 1 = Initialized and ready to exchange data, 2 = Request is running
	this.stack = [];
	this.callback = callback;

	//Fire transport
	var trans = client.option.transport;
	var args = Array.prototype.slice.call(arguments);
	if(typeof trans == "object"){
		for(var t in trans){
			var ret = APS.transport[trans[t]].apply(this, args);
			if(ret != false) break;
		}
	}
	if(typeof trans == "string"){
		APS.transport[trans].apply(this, args);
	}
}

APS.transport.wb = function(server, callback, client){
	if('WebSocket' in window){
		this.id = 6;
		this.loop = setInterval(client.check.bind(client,true), 40000);

		try{
			var ws = new WebSocket('ws://' + server + '/6/');
		}catch(e){
			callback.onerror(e);
			return false
		}

		this.send = function(str){
			if(this.state > 0) ws.send(str);
			else this.stack.push(str);
		}.bind(this);

		ws.onerror = function(e){
			this.state = 0;
			clearInterval(this.loop);
			callback.onerror(e);
		}.bind(this)

		ws.onopen = function(){
			this.state = 2;

			for(var i = 0; i < this.stack.length; i++) this.send(this.stack[i]);
			this.stack = [];

		}.bind(this);

		ws.onmessage = function(ev){
			callback.onmessage(ev.data);
		}
	}else{
		client.log("No Websocket support");
		return false;
	}
}

APS.transport.lp = function(server, callback, client){
	this.id = 0;
	var frame = document.createElement('iframe');
	var protocol = !!client.option.secure ? "https" : "http";
	var origin = window.location.protocol+'//'+window.location.host;

	this.frame = frame;

	with(frame.style){
		position = 'absolute';
		left = top = '-10px';
		width = height = '1px';
	}

	frame.setAttribute('src', protocol + "://" + server + '/?[{"cmd":"frame","params": {"origin":"'+origin+'"}}]');

	document.body.appendChild(frame);

	function recieveMessage(ev){
		if(ev.origin != protocol + "://" + server) return;
		if(ev.source !== frame.contentWindow) return;

		this.state = 1;
		this.callback.onmessage(ev.data);
		//this.callback.once(ev.data);
		//this.callback.once = function(){};
	}
	function onLoad(){
		this.state = 1;

		for(var i = 0; i < this.stack.length; i++) this.send(this.stack[i]);
		this.stack = [];
	}

	if('addEventListener' in window){
		window.addEventListener('message', recieveMessage.bind(this), 0);
		frame.addEventListener('load', onLoad.bind(this), 0);
	} else {
		window.attachEvent('onmessage', recieveMessage.bind(this));
	}

	this.send = function(str, callback){
		if(this.state > 0){
			this.frame.contentWindow.postMessage(str, protocol + "://" + server);
			this.state = 2;
		} else this.stack.push(str);

		if(typeof callback == "function") callback();
		//this.callback.once = callback || function(){};
	}
}<commit_msg>new close() method for all transports<commit_after>//var APSTransport = function(server, callback, options){
APS.transport = function(server, callback, client){
	this.state = 0;//0 = Not initialized, 1 = Initialized and ready to exchange data, 2 = Request is running
	this.stack = [];
	this.callback = callback;

	//Fire transport
	var trans = client.option.transport;
	var args = Array.prototype.slice.call(arguments);
	if(typeof trans == "object"){
		for(var t in trans){
			var ret = APS.transport[trans[t]].apply(this, args);
			if(ret != false) break;
		}
	}
	if(typeof trans == "string"){
		APS.transport[trans].apply(this, args);
	}
}

APS.transport.wb = function(server, callback, client){
	if('WebSocket' in window){
		this.id = 6;
		this.loop = setInterval(client.check.bind(client,true), 40000);

		try{
			var ws = new WebSocket('ws://' + server + '/6/');
		}catch(e){
			callback.onerror(e);
			return false
		}

		this.send = function(str){
			if(this.state > 0) ws.send(str);
			else this.stack.push(str);
		}.bind(this);

		ws.onerror = function(e){
			this.state = 0;
			clearInterval(this.loop);
			callback.onerror(e);
		}.bind(this)

		ws.onopen = function(){
			this.state = 2;

			for(var i = 0; i < this.stack.length; i++) this.send(this.stack[i]);
			this.stack = [];

		}.bind(this);

		ws.onmessage = function(ev){
			callback.onmessage(ev.data);
		}

		ws.onclose = function(){
			clearInterval(this.loop);
			this.state = client.state = 0;
		}

		this.close = function(){
			ws.close();
			this.state = client.state = 0;
		}

	}else{
		client.log("No Websocket support");
		return false;
	}
}

APS.transport.lp = function(server, callback, client){
	this.id = 0;
	var frame = document.createElement('iframe');
	var protocol = !!client.option.secure ? "https" : "http";
	var origin = window.location.protocol+'//'+window.location.host;

	with(frame.style){
		position = 'absolute';
		left = top = '-10px';
		width = height = '1px';
	}

	frame.setAttribute('src', protocol + "://" + server + '/?[{"cmd":"frame","params": {"origin":"'+origin+'"}}]');

	document.body.appendChild(frame);

	function recieveMessage(ev){
		if(ev.origin != protocol + "://" + server) return;
		if(ev.source !== frame.contentWindow) return;

		this.state = 1;
		this.callback.onmessage(ev.data);
		//this.callback.once(ev.data);
		//this.callback.once = function(){};
	}
	function onLoad(){
		this.state = 1;

		for(var i = 0; i < this.stack.length; i++) this.send(this.stack[i]);
		this.stack = [];
	}

	if('addEventListener' in window){
		window.addEventListener('message', recieveMessage.bind(this), 0);
		frame.addEventListener('load', onLoad.bind(this), 0);
	} else {
		window.attachEvent('onmessage', recieveMessage.bind(this));
	}

	this.send = function(str, callback){
		if(this.state > 0){
			frame.contentWindow.postMessage(str, protocol + "://" + server);
			this.state = 2;
		} else this.stack.push(str);

		if(typeof callback == "function") callback();
		//this.callback.once = callback || function(){};
	}

	this.close = function(){
		clearTimeout(client.poller);
		frame.parentElement.removeChild(frame);
		this.state = client.state = 0;
	}
}<|endoftext|>


<commit_before>/*

 lisTours bundle entry point (index.js). use webpack lazy loading to
  load the dependencies of lisTours: jquery and
  bootstrap-tour-standalone.

 */
'use strict';

var lisTours = {}; /* the lisTours library, created by this module */

(function(){
  var that = this;
  var TOUR_ID_KEY = 'lisTourId';
  var VISITED_KEY = 'lisTourVisited';
  var MS = 10; /* interval for checking on dynamic content */
  var MAX_MS = 10000;
  var dependenciesLoaded = false;
  var $ = null;

  if(! window.console )
  {
    // support console.log on old IE versions, if it doesn't exist
    require.ensure(['console-shim'], function(require) {
      require('console-shim');
    });
  }

  this._loadDeps = function(cb) {

    function loader() {
      // lazy-load bootstrap-tour-standalone (includes bootstrap reqs)
      require.ensure(
	['!style!css!../css/bootstrap-tour-standalone.min.css',
	 '!style!css!../css/lis-tours.css',
	 './bootstrap-tour-standalone-loader.js',
	 './tours/index.js'],
	function(require) {
	  console.log('loading bootstrap-standalone-tour');
	  require('!style!css!../css/bootstrap-tour-standalone.min.css');
	  require('!style!css!../css/lis-tours.css');
	  require('./bootstrap-tour-standalone-loader.js');
	  require('./tours/index.js');
	  cb.call(that);
	});
    }

    // lazy load the latest jquery
    require.ensure(['jquery'], function(require) {
      $ = window.__jquery = require('jquery').noConflict(true);
      $(document).ready(loader);
      console.log('using jquery: '+ $.fn.jquery);
    });
  };

  /* go() : force a tour to start at step 0, or the specific step num.
   */
  this.go = function(tourId, stepNum) {
    that._loadDeps(function() {
      var tour = that.tours[tourId];
      if(! tour) {
        localStorage.removeItem(TOUR_ID_KEY);
        throw 'failed to load tour id: ' + tourId;
      }
      tour.init();
      tour.end();
      tour.restart(true);
      if(stepNum) {
        tour.goTo(stepNum);
      }
      localStorage[TOUR_ID_KEY] = tourId;
      _visited(tourId);
    });
  };

  function _visited(tourId) {
    var j = localStorage.getItem(VISITED_KEY) || '{}';
    var visited = JSON.parse(j);
    visited[tourId] = true;
    j = JSON.stringify(visited);
    localStorage.setItem(VISITED_KEY, j);
  }

  /* resume() : restore a tour at whatever step bootstrap tour has
   * retained state.
   */
  this.resume = function(tourId) {
    that._loadDeps(function() {
      var tour = that.tours[tourId];
      if(! tour) {
        localStorage.removeItem(TOUR_ID_KEY);
        throw 'failed to load tour id: ' + tourId;
      }
      tour.init();
      if(tour.ended()) {
        //console.log('removing tour id: ' + tourId) ;
        localStorage.removeItem(TOUR_ID_KEY);
      }
      else {
        var force = true;
        tour.start(force);
      }
    })
  };

  this.tours = {};

  /* register() : each tour object must register, so we can lookup the
   * tour object by it's tag name.
   */
  this.register = function(tour) {
    var name = tour._options.name;
    that.tours[name] = tour;
  };

  /* waitForSelector() : a wrapper for waitForContent(). Use this to wait for
   * existence of a jquery selector string.
   */
  this.waitForSelector = function(tour, jquerySelector, timeout) {
    console.log(jquerySelector);
    return that.waitForContent(
      tour,
      function() {
	return ($(jquerySelector).length > 0);
      },
      timeout);
  };

  /* waitForContent(): provide a callback function which will resolve
   * a promise when the callback returns truthy. Useful for onShow()
   * and onShown() for example.
   */
  this.waitForContent = function(tour, cb, timeout) {
    var promise = new $.Deferred();
    var elapsed = 0;
    var maxMs = timeout || MAX_MS;

    function waiter() {
      var res = cb();
      if(res) {
        promise.resolve();
        return;
      }
      else {
        elapsed += MS;
        if(elapsed >= maxMs) {
          tour.end();
          throw 'error: dynamic content timeout ' + elapsed + ' ms : ' + cb;
        }
        console.log('waiting for dynamic content from callback ' + cb);
        setTimeout(waiter, MS);
      }
    }
    setTimeout(waiter, MS);
    return promise;
  };

  /* init() : lookup the most recent tour id, and load it's module, to
   * enable tour to resume automatically.
   */
  this._init = function() {
    var tourId = localStorage.getItem(TOUR_ID_KEY);
    if(tourId) {
      that.resume(tourId);
    }
  };

  function _jQueryRequired() {
    if (! window.jQuery) {
      return true;
    }
    try {
      var version = parseFloat(window.jQuery.fn.jquery);
      console.log('existing jquery: ' + window.jQuery.fn.jquery);
      var required = (version < JQUERY_MIN_VER || version > JQUERY_MAX_VER);
      return required;
    }
    catch(e) {
      return true;
    }
  }

  this._init();

}.call(lisTours));

// make the lisTours library available globally
module.exports = lisTours;
window.lisTours = lisTours;
//console.log('lisTours loaded');
<commit_msg>Add some checking for required paramters.<commit_after>/*

 lisTours bundle entry point (index.js). use webpack lazy loading to
  load the dependencies of lisTours: jquery and
  bootstrap-tour-standalone.

 */
'use strict';

var lisTours = {}; /* the lisTours library, created by this module */

(function(){
  var that = this;
  var TOUR_ID_KEY = 'lisTourId';
  var VISITED_KEY = 'lisTourVisited';
  var MS = 10; /* interval for checking on dynamic content */
  var MAX_MS = 10000;
  var dependenciesLoaded = false;
  var $ = null;

  if(! window.console )
  {
    // support console.log on old IE versions, if it doesn't exist
    require.ensure(['console-shim'], function(require) {
      require('console-shim');
    });
  }

  this._loadDeps = function(cb) {

    function loader() {
      // lazy-load bootstrap-tour-standalone (includes bootstrap reqs)
      require.ensure(
	['!style!css!../css/bootstrap-tour-standalone.min.css',
	 '!style!css!../css/lis-tours.css',
	 './bootstrap-tour-standalone-loader.js',
	 './tours/index.js'],
	function(require) {
	  console.log('loading bootstrap-standalone-tour');
	  require('!style!css!../css/bootstrap-tour-standalone.min.css');
	  require('!style!css!../css/lis-tours.css');
	  require('./bootstrap-tour-standalone-loader.js');
	  require('./tours/index.js');
	  cb.call(that);
	});
    }

    // lazy load the latest jquery
    require.ensure(['jquery'], function(require) {
      $ = window.__jquery = require('jquery').noConflict(true);
      $(document).ready(loader);
      console.log('using jquery: '+ $.fn.jquery);
    });
  };

  /* go() : force a tour to start at step 0, or the specific step num.
   */
  this.go = function(tourId, stepNum) {
    that._loadDeps(function() {
      var tour = that.tours[tourId];
      if(! tour) {
        localStorage.removeItem(TOUR_ID_KEY);
        throw 'failed to load tour id: ' + tourId;
      }
      tour.init();
      tour.end();
      tour.restart(true);
      if(stepNum) {
        tour.goTo(stepNum);
      }
      localStorage[TOUR_ID_KEY] = tourId;
      _visited(tourId);
    });
  };

  function _visited(tourId) {
    var j = localStorage.getItem(VISITED_KEY) || '{}';
    var visited = JSON.parse(j);
    visited[tourId] = true;
    j = JSON.stringify(visited);
    localStorage.setItem(VISITED_KEY, j);
  }

  /* resume() : restore a tour at whatever step bootstrap tour has
   * retained state.
   */
  this.resume = function(tourId) {
    that._loadDeps(function() {
      var tour = that.tours[tourId];
      if(! tour) {
        localStorage.removeItem(TOUR_ID_KEY);
        throw 'failed to load tour id: ' + tourId;
      }
      tour.init();
      if(tour.ended()) {
        //console.log('removing tour id: ' + tourId) ;
        localStorage.removeItem(TOUR_ID_KEY);
      }
      else {
        var force = true;
        tour.start(force);
      }
    })
  };

  this.tours = {};

  /* register() : each tour object must register, so we can lookup the
   * tour object by it's tag name.
   */
  this.register = function(tour) {
    var name = tour._options.name;
    that.tours[name] = tour;
  };

  /* waitForSelector() : a wrapper for waitForContent(). Use this to wait for
   * existence of a jquery selector string.
   */
  this.waitForSelector = function(tour, jquerySelector, timeout) {
    if(! tour) { throw 'tour parameter required'; }
    if(! jquerySelector) { throw 'jquerySelector parameter required'; }
    console.log(jquerySelector);
    return that.waitForContent(
      tour,
      function() {
	return ($(jquerySelector).length > 0);
      },
      timeout);
  };

  /* waitForContent(): provide a callback function which will resolve
   * a promise when the callback returns truthy. Useful for onShow()
   * and onShown() for example.
   */
  this.waitForContent = function(tour, cb, timeout) {
    if(! tour) { throw 'tour parameter required'; }
    if(! cb) { throw 'callback parameter required'; }
    var promise = new $.Deferred();
    var elapsed = 0;
    var maxMs = timeout || MAX_MS;

    function waiter() {
      var res = cb();
      if(res) {
        promise.resolve();
        return;
      }
      else {
        elapsed += MS;
        if(elapsed >= maxMs) {
          tour.end();
          throw 'error: dynamic content timeout ' + elapsed + ' ms : ' + cb;
        }
        console.log('waiting for dynamic content from callback ' + cb);
        setTimeout(waiter, MS);
      }
    }
    setTimeout(waiter, MS);
    return promise;
  };

  /* init() : lookup the most recent tour id, and load it's module, to
   * enable tour to resume automatically.
   */
  this._init = function() {
    var tourId = localStorage.getItem(TOUR_ID_KEY);
    if(tourId) {
      that.resume(tourId);
    }
  };

  function _jQueryRequired() {
    if (! window.jQuery) {
      return true;
    }
    try {
      var version = parseFloat(window.jQuery.fn.jquery);
      console.log('existing jquery: ' + window.jQuery.fn.jquery);
      var required = (version < JQUERY_MIN_VER || version > JQUERY_MAX_VER);
      return required;
    }
    catch(e) {
      return true;
    }
  }

  this._init();

}.call(lisTours));

// make the lisTours library available globally
module.exports = lisTours;
window.lisTours = lisTours;
//console.log('lisTours loaded');
<|endoftext|>


<commit_before>// Original code by Andy E of Stack Overflow
// http://stackoverflow.com/a/7676115/959934
// Modified by me to allow multiple values to be associated with a single key
function getURLParams(useOrderedList) {
    var urlParams = {};
    var orderedList = [];
    var e,
    a = /\+/g,  // Regex for replacing addition symbol with a space
    r = /([^&=;]+)=?([^&;]*)/g,
    d = function (s) {
        //Returns the original string if it can't be URI component decoded
        var spaced = s.replace(a, " ");
        try {
            return decodeURIComponent(spaced);
        }
        catch(e) {
            return spaced;
        }
    },
    q = window.location.hash;
    if (q.charAt(0) == '#') {
        q = q.substring(1);
    }

    while (e = r.exec(q)) {
        var key = d(e[1]);
        var value = d(e[2]);
        if (useOrderedList) {
            var listItem = new Object();
            listItem['value'] = value;
            listItem['key'] = key;
            orderedList.push(listItem);
        }
        else {
            if (!urlParams[key]) {
                urlParams[key] = [value];
            }
            else {
                // If key already found in the query string, the value is tacked on
                urlParams[key].push(value);
            }
        }
    }
    if (useOrderedList) {
        return orderedList;
    }
    else {
        return urlParams;
    }
};

function addHashParam(key, value) {
    var currentHash = window.location.hash;
    if (!currentHash.length) {
        return key + "=" + value;
    }
    else return currentHash + "&" + key + "=" + value;
}

$(document).ready(function() {
    var urlParams = getURLParams(true);
    $.ajaxSetup({
        async: false
    });
    if (urlParams) {
        soundManager.onready(function(status) {
            var inputCount = urlParams.length;
            if (inputcount) {
                $.blockUI();
                router.playlistObject.updateSettings({
                    updateURLOnAdd: false
                });
                for (var param in urlParams) {
                    var keyValuePair = urlParams[param];
                    switch(keyValuePair.key.toString().toLowerCase()) {
                        case 'ytv':
                            if (keyValuePair.value) {
                                router.processYouTubeVideoID(keyValuePair.value, 'pageload');
                            }
                            break;
                        case 'sct':
                            if (keyValuePair.value) {
                                router.processSoundCloudTrack(keyValuePair.value, 'pageload');
                            }
                            break;
                        case 'scp':
                            if (keyValuePair.value) {
                                router.processSoundCloudPlaylist(keyValuePair.value, 'pageload');
                            }
                            break;
                        case 'bct':
                            if (keyValuePair.value) {
                                router.processBandcampTrack(keyValuePair.value, 'pageload');
                            }
                            break;
                        case 'bca':
                            if (keyValuePair.value) {
                                router.processBandcampAlbum(keyValuePair.value, 'pageload');
                            }
                            break;
                    }
                }
                var interval = window.setInterval(function() {
                    if (!document.ajaxq.q['pageload'].length) {
                        window.clearInterval(interval);
                        router.playlistObject.updateSettings({
                            updateURLOnAdd: true
                        });
                        $.unblockUI();
                    }
                }, 100);
            }
        });
    }
});<commit_msg>Fixed typo that would prevent playlist from loading from hash.<commit_after>// Original code by Andy E of Stack Overflow
// http://stackoverflow.com/a/7676115/959934
// Modified by me to allow multiple values to be associated with a single key
function getURLParams(useOrderedList) {
    var urlParams = {};
    var orderedList = [];
    var e,
    a = /\+/g,  // Regex for replacing addition symbol with a space
    r = /([^&=;]+)=?([^&;]*)/g,
    d = function (s) {
        //Returns the original string if it can't be URI component decoded
        var spaced = s.replace(a, " ");
        try {
            return decodeURIComponent(spaced);
        }
        catch(e) {
            return spaced;
        }
    },
    q = window.location.hash;
    if (q.charAt(0) == '#') {
        q = q.substring(1);
    }

    while (e = r.exec(q)) {
        var key = d(e[1]);
        var value = d(e[2]);
        if (useOrderedList) {
            var listItem = new Object();
            listItem['value'] = value;
            listItem['key'] = key;
            orderedList.push(listItem);
        }
        else {
            if (!urlParams[key]) {
                urlParams[key] = [value];
            }
            else {
                // If key already found in the query string, the value is tacked on
                urlParams[key].push(value);
            }
        }
    }
    if (useOrderedList) {
        return orderedList;
    }
    else {
        return urlParams;
    }
};

function addHashParam(key, value) {
    var currentHash = window.location.hash;
    if (!currentHash.length) {
        return key + "=" + value;
    }
    else return currentHash + "&" + key + "=" + value;
}

$(document).ready(function() {
    var urlParams = getURLParams(true);
    $.ajaxSetup({
        async: false
    });
    if (urlParams) {
        soundManager.onready(function(status) {
            var inputCount = urlParams.length;
            if (inputCount) {
                $.blockUI();
                router.playlistObject.updateSettings({
                    updateURLOnAdd: false
                });
                for (var param in urlParams) {
                    var keyValuePair = urlParams[param];
                    switch(keyValuePair.key.toString().toLowerCase()) {
                        case 'ytv':
                            if (keyValuePair.value) {
                                router.processYouTubeVideoID(keyValuePair.value, 'pageload');
                            }
                            break;
                        case 'sct':
                            if (keyValuePair.value) {
                                router.processSoundCloudTrack(keyValuePair.value, 'pageload');
                            }
                            break;
                        case 'scp':
                            if (keyValuePair.value) {
                                router.processSoundCloudPlaylist(keyValuePair.value, 'pageload');
                            }
                            break;
                        case 'bct':
                            if (keyValuePair.value) {
                                router.processBandcampTrack(keyValuePair.value, 'pageload');
                            }
                            break;
                        case 'bca':
                            if (keyValuePair.value) {
                                router.processBandcampAlbum(keyValuePair.value, 'pageload');
                            }
                            break;
                    }
                }
                var interval = window.setInterval(function() {
                    if (!document.ajaxq.q['pageload'].length) {
                        window.clearInterval(interval);
                        router.playlistObject.updateSettings({
                            updateURLOnAdd: true
                        });
                        $.unblockUI();
                    }
                }, 100);
            }
        });
    }
});<|endoftext|>