CoffeeScript

by Serge Zahharenko

HTML

<script src="http://code-essence.eu/preview/alltreands/coffee-script.js"></script>
<script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
<h1>Test assigment</h1>
<div id="buttons">
	<button id="save">Save current satate</button>
	<button id="restore">Restore saved</button>
	<button id="reset">Reset</button>
</div>
<ul id="list"></ul>
<div id="system"><pre id="log"></pre></div>

<script id="listTemplate" type="text/html">
	<li class="item">
		<span class="name">${name}</span>
		{{if children}}
			<ul>
				{{tmpl(children) '#listTemplate'}}
				{{tmpl() '#newItemTemplate'}}
			</ul>
		{{/if}}
	</li>
</script>
<script id="newItemTemplate" type="text/html">
	<li class="add-item">Add element</li>
</script>

<script>
	var list_data = [
		{name: 'Element #1'},
		{name: 'Element #2'},
		{name: 'Element #3',
		 children: [
			{
				name:'Child #1 of element #3',
				children: [
					{name:'Subchild'},
					{name:'Another subchild'},
					{name:'Another subchild'},
					{name:'Last subchild'},
				]
			},
			{
				name:'Child #2 of element #3',
				children: [
					{name:'Subchild'},
					{name:'Subchild'},
					{name:'Subchild'},
					{name:'Subchild'},
				]
			},
			{
				name:'Child #3 of element #3',
				children: [
					{name:'Subchild'},
					{name:'Subchild'}
				]
			}
		 ]
		},
		{name: 'Element #4'}
	]
</script>

CSS

* {padding:0;margin:0;}
body {padding:60px;}
ul {padding-left:20px;border-left:solid 1px #ccc;}

#buttons {padding:10px;color:red;}

#list {width:400px;float:left;}
#list ul {padding-top:10px;position:relative;margin-top:10px;margin-bottom:20px;}
#list ul:after {content:'';display:block;clear:both;}
#list ul:before {content:'';position:absolute;top:0;right:100%;height:1px;background:#ccc;width:20px;}
#list li {float:left;clear:both;}
#list li > span {display:inline-block;padding:4px;cursor:pointer;height:15px;}
#list li input {box-sizing:border-box;height:23px;padding:4px;}
#list li > span:hover {background:#efefef;}
#list li.contexted > span {background:yellow;}
#list li.add-item {color:green;cursor:pointer;padding:4px;}
#list li.add-item:hover {color:red;}

/* CONTEXT MENU */
.context {display:none;position:absolute;z-index:1000;color:#000;font-size:11px;max-width:250px;background-color:#fffcd9;border: solid 1px #ccc;border-top: none;border-left: none;border-top: none;  border-bottom: none;-webkit-box-shadow: #777 1px 1px 4px;-moz-box-shadow: #777 1px 1px 4px;box-shadow: #777 1px 1px 4px;overflow: hidden;white-space: nowrap;border:solid 5px transparent;}
.context.clean {border: none;padding: 0;box-shadow: none;background: none;overflow:visible;}
.context > a {color: #555;display:block;padding: 4px 15px;min-width: 30px;position: relative;text-decoration:none;font-size:12px;cursor:pointer;font-size:16px;}
.context > a:hover {color: #000;background-color: #fff;}

/* TESTING ENVIROMENT */
#list + div {overflow:hidden;}
#tests,
#log {float:left;color:green;line-height: 12px;font-size: 12px;clear:left;margin-bottom:30px;}
#tests {font-size:25px;line-height:25px;color:blue;}

CoffeeScript

APP =
  init: ->
    list = $("#list")
    list.html(APP.template("#listTemplate", list_data)).append $.tmpl($("#newItemTemplate"))
    @bindList list
    if typeof localStorage is "object"
      @initStorage list
    else
      $("#buttons").text "local storage not supported"
    return

  bindList: (list) ->
    list.on("click", ".add-item", (e) ->
      e.stopPropagation()
      APP.rename $(this), true
      return
    ).on "click", ".item:not(.editing)", (e, data) ->
      e.stopPropagation()
      e.preventDefault()
      li = $(this)
      contextMarkup = ""
      contextMarkup += "<a class=\"rename\"><span></span>Rename</a>"
      contextMarkup += "<a class=\"delete\"><span></span>Delete</a>"
      context.create e, contextMarkup, true
      $("#context .rename").click (e) ->
        APP.rename li
        context.close()
        return

      $("#context .delete").click (e) ->
        APP.remove li
        context.close()
        return

      return

    return

  initStorage: (list) ->
    current = localStorage.getItem("APP_list")
    $("#save").click ->
      j = APP.serializeUL("#list")
      localStorage.setItem "APP_list", JSON.stringify(j)
      $("#restore").attr "disabled", false
      return

    $("#restore").attr((if current then "data" else "disabled"), (if current then " " else "disabled")).click ->
      j = JSON.parse(localStorage.getItem("APP_list"))
      list.html APP.template("#listTemplate", j)
      return

    $("#reset").click ->
      list.html APP.template("#listTemplate", list_data)
      localStorage.getItem "APP_list"
      return

    return

  createId: ->
    id = new Date()
    id = "id" + id.getTime()
    id

  remove: (li) ->
    li.remove()
    APP.log()
    return

  rename: (li, new_child) ->
    id = @createId()
    if new_child
      li.before "<li class=\"item editing\"><span class=\"name\"><input id=\"" + id + "\" value=\"\"/></span></li>"
    else
      name = $(li).children(".name")
      text = name.text()
   ...