Abstract.js Document  GitHub  Team Blog

Abstract 2.0

Rock Yourself In Mess Code

Abstract Math Theory

Abstract.js is based on abstract math theory. It puts new concept into Web Development.Learn Basic Concept & Theory

Virtual DOM

Models refer to page block. Each Models has children and one parent. Thus it constructs a virtual dom tree.

Event Progation

Events emmitted by one models can propagate to the top of the virtual dom tree. So you can capture the event on the root node or stop propagation.

Strict MVC

Every piece of code looks so familar. Abstract reduces the chance of refactoring your project.

Easy And Fast

It takes few minutes to build one mobile page. So fast!

Friendly With Lib

If you're using jQuery or zepto, the ajax module will be handled by the lib.

Who Are Using Abstract?

QQ Tribes
QQ Group Activities
More of You

Let's see what Abstract can do.

Rendering

var header = new RenderModel({
  el: "#render",
  data: {
    title: "Abstract.js",
    desc: "Abstract.js is next framework for the web"
  },

  tmpl: "{{title}}<br />{{desc}}"
});

header.rock();
          

Listing

Try scrolling to bottom
      var listing = new ScrollModel({
          data: {
          list: [
            'Abstact.js publishes version 2.0',
            'Abstact.js publishes version 2.0',
            'Abstact.js publishes version 2.0',
            'Abstact.js publishes version 2.0',
            'Abstact.js publishes version 2.0'
          ]
        },

        scrollEl: '#listing',
        tmpl: "<li soda-repeat='item in list'>{{item}}</li>",
        el: "#listing"
      });

      listing.rock();
          
    载入中

    Tabs

    
    var tab1 = new RenderModel({
      el: ".tabpage",
      data: {
        name: "tab1"
      },
      tmpl: "{{name}}"
    });
    
    var tab2 = tab1.extend({
      data: {
        name: "tab2"
      }
    });
    
    var tab3 = tab1.extend({
      data: {
        name: "tab3"
      }
    });
    
    // Telling The Relationship Between Models
    var tab = new MultitabModel();
    tab.add(".tab1", tab1);
    tab.add(".tab2", tab2);
    tab.add(".tab3", tab3);
    
    tab.rock();
              
    • tab1
    • tab2
    • tab3

    Paging

    var pageList = new RenderModel({
        el: ".contentList",
        tmpl: "<li soda-repeat='item in list'>{{item}}</li>",
        data: {
          list: [
            "第1页数据"
          ]
        },
    
        processData: function(){
        }
    });
    
    var pagation = new RenderModel({
        el: ".pagation",
        tmpl: "<li data-index='{{$index + 1}}' class='pageItem' soda-repeat='item in list'>{{$index + 1}}</li>",
        data: {
          list: new Array(10)
        },
    
        processData: function(){
        },
    
        events: function(){
          var els = document.querySelectorAll(".pageItem");
    
          for(var i = 0; i < els.length; i ++){
            var el = els[i];
    
            el.onclick = function(){
              var index = this.getAttribute("data-index");
    
              pageList.data = {
                list: [
                ]
              };
    
              for(var j = 0; j < index; j ++){
                pageList.data.list.push("第" + (index) + "页数据");
              }
    
              pageList.refresh();
            };
          }
        }
    });
    
    // Telling The Relationship Between Models
    var pageWrapper = new PageModel();
    pageWrapper.add(pageList);
    pageWrapper.add(pagation);
    
    pageWrapper.rock(); 
              

        Quick Mobile Page

        var header = new RenderModel({
            el: "#header",
            data: {
              name: "Header"
            },
            tmpl: "{{name}}"
        });
        
        var newsList = new ScrollModel({
          data: {
            list: [
              'Abstact.js publishes version 2.0',
              'Abstact.js publishes version 2.0',
              'Abstact.js publishes version 2.0',
              'Abstact.js publishes version 2.0',
              'Abstact.js publishes version 2.0'
            ]
          },
        
          scrollEl: '.subpage1',
          tmpl: "<li soda-repeat='item in list'>{{item}}</li>",
          el: ".subpage1 ol"
        });
        
        var newsTab = new PageModel();
        var newsFrame = new RenderModel({
            tmpl: "<ol></ol><div>加载中</div>",
            el: ".subpage1",
            onreset: function(){
              document.querySelector(".subpage1").innerHTML = "";
            }
        });
        
        newsTab.add(newsFrame);
        newsTab.add(newsList);
        
        var me = new RenderModel({
              tmpl: "Me Tab",
              el: ".subpage2"
        });
        var setting = me.extend({
            tmpl: "Setting Tab",
            el: ".subpage3"
        });
        
        
        // Telling The Relationship Between Models
        var tabs = new MultitabModel();
        tabs.add(".news", newsTab);
        tabs.add(".me", me);
        tabs.add(".setting", setting);
        
        var page = new PageModel();
        page.add(header);
        page.add(tabs);
        
        page.rock();
                  
        • news
        • me
        • settings

        Higher Level Usage

        Dialog

        // dialog
        var dialogRender = new RenderModel({
          data: {
            title: "Dialog",
            content: "Abstact publishes Version 2.0"
          },
          fuse: Model.createFuse("click", "#showDialog"),
        
          el: ".dialogWrapper",
          tmpl: "<h2>{{title}}<span class='close'>close</span></h2>&tl;div class='dialogContent'>{{content}}</div>"
        });
        
        dialogRender.addEventListener("beforeactived", function(){
            document.querySelector(".dialogWrapper").innerHTML = "";
            this.show();
        });
        
        dialogRender.addEventListener("unactived", function(){
            this.hide();
        });
        
        
        var closeModel = new BaseModel({
            fuse: Model.createFuse("click", ".close")
        });
        
        // Telling The Relationship Between Models
        var controller = new MutexModel();
        controller.add(closeModel);
        controller.add(dialogRender);
        
        controller.rock();
        
                  
        Show Dialog

        Dialog(Using MultitabModel, less code)

        // dialog
        var dialogRender2 = new RenderModel({
          data: {
            title: "Dialog",
            content: "Abstact publishes Version 2.0"
          },
        
          el: ".dialogWrapper2",
          tmpl: "<h2>{{title}}<span class='close2'>close</span></h2><div class='dialogContent'>{{content}}</div>"
        });
        
        
        var closeModel2 = new BaseModel({
        });
        
        // Telling The Relationship Between Models
        var controller2 = new MultitabModel();
        controller2.add(".close2", closeModel2);
        controller2.add("#showDialog2", dialogRender2);
        
        controller2.rock();
        
                  
        Show Dialog

        MultiPage with Animation

        var page1 = new PageModel();
        var pageContent = new RenderModel({
          tmpl: "page1 <br /><br /><div class='btn openPage2'>open page2</div>",
          el: ".subpage_1"
        });
        
        page1.add(pageContent);
        pageContent.hide = function(){
          Model.$(this.el).removeClass("current");
        };
        
        pageContent.show = function(){
          Model.$(this.el).addClass("current");
        };
        
        var page2 = page1.extend();
        page2.children[0].tmpl = "page2 <br /><br /><span class='btn closePage2'>back</span>";
        page2.children[0].el = ".subpage_2";
        
        // Telling The Relationship Between Models
        var controllPage = new MultitabModel();
        controllPage.add(".closePage2", page1);
        controllPage.add(".openPage2", page2);
        
        controllPage.rock();
        
                  

        Pic Slider

        The pic comes in the same direction; Just less than 50 lines code to write an perfect pic slider with clear logic without event bindings;
        var picsRender1 = new RenderModel({
          data: {
            src: "girl",
          },
        
          tmpl: "<img soda-src='image/{{src}}.jpg' />",
          
          el: ".pics_1"
        });
        
        picsRender1.show = function(){
          Model.$(this.el).addClass("waiting");
          var _this = this;
          setTimeout(function(){
            Model.$(_this.el).removeClass("waiting");
            Model.$(_this.el).addClass("showAni");
          }, 0);
        };
        
        picsRender1.hide = function(){
          Model.$(this.el).removeClass("showAni");
        };
        
        var picsRender2 = picsRender1.extend({
          data: {
            src: "car"
          },
        
          el: ".pics_2"
        });
        
        var picsRender3 = picsRender1.extend({
          data: {
            src: "dog"
          },
        
          el: ".pics_3"
        });
        
        var controllTab = new MultitabModel();
        controllTab.add(".controll1", picsRender1);
        controllTab.add(".controll2", picsRender2);
        controllTab.add(".controll3", picsRender3);
        
        controllTab.rock();
        
                    

        MVVM Using

        Abstract is not MVVM Framework, but also Abstract can construct MVVM logics as well.
        But Abstract concerns about the logic about datas, not the views.

        To Do

        var todoList = new RenderModel({
          data: {
            list: []
          },
          el: ".toList",
        
          tmpl: "<ul><li soda-repeat='item in list'>{{item}}</li></ul>",
          events: function(){
            var input = document.getElementById("toDoInput");
            var button = document.getElementById("add");
        
            var _this = this;
            add.onclick = function(){
              var text = input.value;
        
              _this.data.list = _this.data.list.concat(text);
        
              input.value = "";
        
              _this.refresh();
            };
          }
        });
        
        todoList.rock();
                  

        To Do

        Markdown Editor

        
        var markdown = new RenderModel({
          el: ".outMd",
          data: {
          content: ""
        },
        events: function(){
          var textarea = document.querySelector("#mdInput");
          var _this = this;
          textarea.addEventListener("input", function(e){
            _this.data.content = marked(this.value, {sanitize: true});
            _this.refresh();
          });
        },
        tmpl: "<span soda-bind-html='content'></span>"
        });
        
        markdown.rock();
        
                  

        Input

        Output

        Progress Bar

        
        var bar = new RenderModel({
            el: "#bar",
            data: {
              width: 0
            },
        
            tmpl: "<div style='width: {{width}}%'></div>",
            events: function(){
              var _this = this;
              setInterval(function(){
                  _this.data.width += 0.3;
        
                  if(_this.data.width > 100){
                    _this.data.width = 0;
                  }
        
                  _this.refresh();
              }, 1000 / 60);
            }
        });
        
        bar.rock(); 
                  
        顶部