function() { var renderer = etpl.compile( text['lazy-target'] ); expect(renderer).toBeNull(); etpl.compile( text['lazy-master'] ); renderer = etpl.getRenderer('masterLazyTarget'); expect(typeof renderer).toBe('function'); expect(renderer()).toBe(text['expect-lazy-target']); }
function (require) { var etpl = require( 'etpl' ); var readText = require( 'readTextSync' ); var text = readText( 'spec/master.text.html' ); var simpleRenderer = etpl.compile( text.simple ); var simple2Renderer = etpl.compile( text.simple2 ); describe('Master', function() { it( 'can be applied to target', function() { expect(simpleRenderer()).toEqual(text[ 'expect-simple' ]); expect(simple2Renderer()).toEqual(text[ 'expect-simple2' ]); } ); it( 'Use contentplaceholder`s content when not be replaced', function() { var renderer = etpl.compile( text['default-cph'] ); expect(renderer()).toEqual(text[ 'expect-default-cph' ]); } ); it( 'can be applied to master', function() { var renderer = etpl.compile( text['applyto-master'] ); expect(etpl.getRenderer('masterChildTargetNoContent')()) .toEqual(text[ 'expect-masterChildTargetNoContent' ]); expect(etpl.getRenderer('masterChildTargetBodyContent')()) .toEqual(text[ 'expect-masterChildTargetBodyContent' ]); expect(etpl.getRenderer('masterChildTargetBHContent')()) .toEqual(text[ 'expect-masterChildTargetBHContent' ]); } ); it( 'Target extends uncompiled master will return null. After master compiled, renderer canbe getted.', function() { var renderer = etpl.compile( text['lazy-target'] ); expect(renderer).toBeNull(); etpl.compile( text['lazy-master'] ); renderer = etpl.getRenderer('masterLazyTarget'); expect(typeof renderer).toBe('function'); expect(renderer()).toBe(text['expect-lazy-target']); } ); }); }
function (require) { var etpl = require( 'etpl' ); var readText = require( 'readTextSync' ); var text = readText( 'spec/import.text.html' ); var data = {name: text.name}; etpl.compile( text['simple'] ); describe('Import', function() { it('can be used in target', function() { var renderer = etpl.getRenderer('importPara'); expect(renderer(data)).toEqual(text['expect-importPara']); }); it('can be used in master applyed, both content and contentplaceholder', function() { var renderer = etpl.getRenderer('importMasterTarget'); expect(renderer(data)).toEqual(text['expect-importMasterTarget']); }); it('When dependence unready, getRenderer should return null. Renderer can be getted when dependence ready.', function() { var renderer = etpl.getRenderer('importMasterTarget2'); expect(renderer).toBeNull(); etpl.compile( text['other-imported'] ); renderer = etpl.getRenderer('importMasterTarget2'); expect(typeof renderer).toBe('function'); expect(renderer(data)).toBe(text['expect-importMasterTarget2']); }); }); }
require([resourceId], function (tpl) { var etpl = require('etpl'); etpl.config({ namingConflict: 'ignore' }); etpl.compile(tpl); load(tpl); });
readFile(task).then(function (file) { try { var render = etpl.compile(file); caches[task] = render; cb(null, render); } catch (e) { cb(e); } }, function (err) {
it('When dependence unready, getRenderer should return null. Renderer can be getted when dependence ready.', function() { var renderer = etpl.getRenderer('importMasterTarget2'); expect(renderer).toBeNull(); etpl.compile( text['other-imported'] ); renderer = etpl.getRenderer('importMasterTarget2'); expect(typeof renderer).toBe('function'); expect(renderer(data)).toBe(text['expect-importMasterTarget2']); });
function() { var renderer = etpl.compile( text['applyto-master'] ); expect(etpl.getRenderer('masterChildTargetNoContent')()) .toEqual(text[ 'expect-masterChildTargetNoContent' ]); expect(etpl.getRenderer('masterChildTargetBodyContent')()) .toEqual(text[ 'expect-masterChildTargetBodyContent' ]); expect(etpl.getRenderer('masterChildTargetBHContent')()) .toEqual(text[ 'expect-masterChildTargetBHContent' ]); }
util.getToWriteData = function (tplPath, data) { var tplData = fs.readFileSync(tplPath, {encoding: 'utf8'}).toString(); var render = etpl.compile(tplData); var basicData = { author: edpConfig.get('user.name'), email: edpConfig.get('user.email') }; return render(util.extend(basicData, data)); };
module.exports = function ( handlebarsSource, data, outputFile ) { var etpl = require( 'etpl' ); // etpl.config({ strip: true }); var template = etpl.compile( handlebarsSource ); var text = template( data ); if ( outputFile ) { require( 'fs' ).writeFileSync( outputFile, text, 'UTF-8' ); } return text; };
define(function (require) { var Component = require('./Component'); var zrUtil = require('zrender/tool/util'); var etpl = require('etpl'); var util = require('../util/util'); var bkgLog = require('../util/log'); var Sizzle = require('Sizzle'); var renderPersonList = etpl.compile(require('text!../html/personList.html')); var renderSearchbar = etpl.compile(require('text!../html/searchBar.html')); var SearchBar = function () { Component.call(this); var self = this; util.addEventListener(this.el, 'click', function (e) { self._dispatchClick(e); }); } SearchBar.prototype.type = 'SEARCHBAR'; SearchBar.prototype.initialize = function (kg, data) { this._kgraph = kg; var el = this.el; el.className = 'bkg-searchbar hidden'; // 使用空数据 this.render(data); } SearchBar.prototype.setData = function (data) { this.render(data); } SearchBar.prototype.render = function (data) { this.el.innerHTML = renderSearchbar(data); this._$viewport = Sizzle('.bkg-person-list-viewport', this.el)[0]; this._$prevPageBtn = Sizzle('.bkg-prev-page', this.el)[0]; this._$nextPageBtn = Sizzle('.bkg-next-page', this.el)[0]; this._$input = Sizzle('.bkg-search-input input', this.el)[0]; this._$toggleBtn = Sizzle('.bkg-toggle', this.el)[0]; this._viewportWidth = this._$viewport.clientWidth; var self = this; util.addEventListener(this._$input, 'keydown', util.debounce(function () { self.filter(self._$input.value); }, 200)); this._updateSlider(); } SearchBar.prototype.resize = function (w, h) { // Do nothing } /** * 隐藏搜索栏 */ SearchBar.prototype.hide = function () { util.addClass(this.el, 'hidden'); this._$toggleBtn.innerHTML = '搜 索<span class="arrow"></span>'; bkgLog('searchhide'); } /** * 显示搜索栏 */ SearchBar.prototype.show = function () { util.removeClass(this.el, 'hidden'); this._$toggleBtn.innerHTML = '隐 藏<span class="arrow"></span>'; var sideBar = this._kgraph.getComponentByType('SIDEBAR'); if (sideBar) { sideBar.hide(); } bkgLog('searchshow'); } /** * 切换搜索栏的显示隐藏 */ SearchBar.prototype.toggle = function () { if (util.hasClass(this.el, 'hidden')) { this.show(); } else { this.hide(); } } /** * 人物列表翻到下一页 */ SearchBar.prototype.nextPage = function () { if (this._isLastPage) { return; } this._left += this._viewportWidth; if (this._left + this._viewportWidth > this._width) { this._left = this._width - this._viewportWidth; this._isLastPage = true; util.addClass(this._$nextPageBtn, 'disable'); } this._$list.style.left = -this._left + 'px'; this._isFirstPage = false; util.removeClass(this._$prevPageBtn, 'disable'); this._loadImage(); } /** * 人物列表翻到上一页 */ SearchBar.prototype.prevPage = function () { if (this._isFirstPage) { return; } this._left -= this._viewportWidth; if (this._left < 0) { this._left = 0; this._isFirstPage = true; util.addClass(this._$prevPageBtn, 'disable'); } this._$list.style.left = -this._left + 'px'; this._isLastPage = false; util.removeClass(this._$nextPageBtn, 'disable'); this._loadImage(); } /** * 过滤人物 */ SearchBar.prototype.filter = function (name) { var data = this._kgraph.getRawData(); var entities = []; if (!name) { entities = data.entities; } else { for (var i = 0; i < data.entities.length; i++) { var entity = data.entities[i]; if (entity.name.indexOf(name) >= 0 || entity.namePinYin && entity.namePinYin.indexOf(name) >= 0 ) { entities.push(entity); } } } this._$viewport.innerHTML = renderPersonList({ entities: entities }); this._updateSlider(); bkgLog('searchinput', name); } /** * 点击人物 */ SearchBar.prototype.clickPerson = function (id) { var graphMain = this._kgraph.getComponentByType('GRAPH'); if (graphMain) { graphMain.highlightNodeToMain(id); graphMain.showEntityDetail(id); graphMain.moveToEntity(id); bkgLog('searchclick', id); } } SearchBar.prototype._dispatchClick= function (e) { var target = e.target || e.srcElement; if (Sizzle.matchesSelector(target, '.bkg-prev-page')) { this.prevPage(); } else if (Sizzle.matchesSelector(target, '.bkg-next-page')) { this.nextPage(); } else if (Sizzle.matchesSelector(target, '.bkg-toggle') || Sizzle.matchesSelector(target, '.bkg-toggle .arrow') ) { this.toggle(); } else if (Sizzle.matchesSelector(target, '.bkg-person *')) { var parent = target; while (parent) { if (parent.className.indexOf('bkg-person') >= 0) { break; } parent = target.parentNode; } var activeDom = Sizzle('.active', this.el)[0]; if(activeDom) { util.removeClass(activeDom, 'active'); } util.addClass(parent, 'active'); this.clickPerson(parent.getAttribute('data-bkg-entity-id')); } } SearchBar.prototype._updateSlider = function () { this._$list = Sizzle('ul', this._$viewport)[0]; this._width = this._$list.clientWidth; this._isLastPage = false; this._isFirstPage = true; if (this._width < this._viewportWidth) { this._isLastPage = true; } this._isLastPage ? util.addClass(this._$nextPageBtn, 'disable') : util.removeClass(this._$nextPageBtn, 'disable'); this._isFirstPage ? util.addClass(this._$prevPageBtn, 'disable') : util.removeClass(this._$prevPageBtn, 'disable'); this._left = 0; this._$imageList = Sizzle('li img', this._$list); var $img = this._$imageList[0]; if ($img) { var $li = $img.parentNode; this._itemWidth = $li.clientWidth; var style = util.getStyle($li); this._itemWidth += parseInt(style['margin-left']) + parseInt(style['margin-right']); } this._loadImage(); } SearchBar.prototype._loadImage = function () { var start = Math.floor(this._left / this._itemWidth); var end = Math.ceil((this._left + this._viewportWidth) / this._itemWidth); for (var i = start; i < end; i++) { var $item = this._$imageList[i]; if ($item && !$item.getAttribute('src')) { $item.src = $item.getAttribute('data-src'); } } } zrUtil.inherits(SearchBar, Component); return SearchBar; });
define(function(require) { var Benchmark = require('benchmark'); var zrender = require('zrender'); var etpl = require('etpl'); var area = require('zrender/tool/area'); var util = require('zrender/tool/util'); var shapeMakers = require('./shapes'); var PathProxy = require('zrender/shape/util/PathProxy'); window.zr = zrender.init(document.getElementById('main')); var canvas = document.getElementById('points'); window.width = zr.getWidth(); window.height = zr.getHeight(); canvas.width = width; canvas.height = height; window.ctx = canvas.getContext('2d'); var suite = new Benchmark.Suite(); var shapeTypes = ['Circle', 'Line', 'Rectangle', 'Star', 'Sector', 'Heart', 'Cubic', 'Quadratic']; // var shapeTypes = ['Curve']; suite.benchmarks = []; suite.on('add', function(e) { suite.benchmarks.push(e.target); }); var renderResult = etpl.compile('<h3>${name}</h3>\ <table>\ <tr>\ <th>shape类型</th>\ <!-- for: ${result} as ${item} -->\ <th>${item.shapeType}</th>\ <!-- /for -->\ </tr>\ <tr>\ <td>op/s</td>\ <!-- for: ${result} as ${item} -->\ <td>${item.ops}</td>\ <!-- /for -->\ </tr>\ </table>'); var shapeList = []; var N_SHAPE = 20; window.N_ITER = 2000; window.points = []; for (var i = 0; i < N_ITER; i++) { points[i] = [0, 0, false]; } function addBenck (funcName, name) { var res = []; var count = shapeTypes.length; var resultDom = document.createElement('div'); resultDom.className = 'result'; document.getElementById('results').appendChild(resultDom); shapeTypes.forEach(function(shapeType) { function setup () { for (var i = 0; i < N_ITER; i++) { var x = Math.random() * width; var y = Math.random() * height; points[i][0] = x; points[i][1] = y; points[i][2] = false; } } function teardown () { for (var i = 0; i < N_ITER; i++) { ctx.fillStyle = points[i][2] ? 'green' : 'red' ctx.fillRect(points[i][0], points[i][1], 2, 2); } } function onComplete(e) { var bench = e.target; res.push({ ops: (N_ITER * N_SHAPE / (bench.stats.mean + bench.stats.moe)).toFixed(0), shapeType: shapeType }); count--; resultDom.innerHTML = renderResult({ result: res, name: name }); } suite.add('ZRender ' + shapeType, { fn: 'for (var i = 0; i < N_ITER; i++) {\n\ points[i][2] = ' + funcName + '(points[i][0], points[i][1]);\n\ }', setup: setup, teardown: teardown, async: true, onError: onError, onStart: function() { zr.storage.delRoot(); for (var i = 0; i < N_SHAPE; i++) { var shape = shapeMakers['make' + shapeType](width, height); if (!shape._pathProxy) { shape._pathProxy = new PathProxy(); shape.buildPath(shape._pathProxy, shape.style); } shapeList[i] = shape; zr.addShape(shape); } zr.refresh(); ctx.clearRect(0, 0, width, height); }, onComplete: onComplete }); function onError(err) { console.log(err.message.message); } }); } document.getElementById('run').addEventListener('click', function() { window['mathMethod'] = function (x, y) { for (var j = 0; j < N_SHAPE; j++) { var shape = shapeList[j]; if (area.isInside(shape, shape.style, x, y)) { return true; } } } window['buildPath'] = function (x, y) { for (var j = 0; j < N_SHAPE; j++) { var shape = shapeList[j]; ctx.beginPath(); shape.buildPath(ctx, shape.style); ctx.closePath(); shape.brushType = shape.brushTypeOnly || shape.brushType; if ( shape.style.brushType === 'fill' || shape.style.brushType === 'both' ) { if (ctx.isPointInPath(x, y)) { return true; } } else if ( shape.style.brushType === 'stroke' || shape.style.brushType === 'both') { ctx.lineWidth = shape.style.lineWidth; if (ctx.isPointInStroke(x, y)) { return true; } } } } window['jsInsidePath'] = function (x, y) { for (var j = 0; j < N_SHAPE; j++) { var shape = shapeList[j]; if (area.isInsidePath( shape._pathProxy.pathCommands, shape.style.lineWidth, shape.style.brushType, x, y )) { return true; } } } function _isPainted(context, x, y, unit) { var pixelsData; if (typeof unit != 'undefined') { unit = (unit || 1) >> 1; pixelsData = context.getImageData( x - unit, y - unit, unit + unit, unit + unit ).data; } else { pixelsData = context.getImageData(x, y, 1, 1).data; } var len = pixelsData.length; while (len--) { if (pixelsData[len] !== 0) { return true; } } return false; } window['pixelMethod'] = function (x, y) { for (var j = 0; j < N_SHAPE; j++) { var shape = shapeList[j]; var _rect = shape.getRect(shape.style); var _context = util.getPixelContext(); var _offset = util.getPixelOffset(); util.adjustCanvasSize(x, y); _context.clearRect(_rect.x, _rect.y, _rect.width, _rect.height); _context.beginPath(); shape.brush(_context, { style: shape.style }); _context.closePath(); if (_isPainted(_context, x + _offset.x, y + _offset.y)) { return true; } } } // addBenck('mathMethod', 'Math method'); addBenck('buildPath', 'Native isPointInPath'); addBenck('jsInsidePath', 'JS isPointInPath'); // addBenck('pixelMethod', 'pixelMethod'); suite.run(); }); suite.on('complete', function() { var benches = Benchmark.filter(suite.benchmarks, 'successful'); }); });
define(["require","benchmark","zrender","etpl","zrender/tool/area","zrender/tool/util","./shapes","zrender/shape/util/PathProxy"],function(require){function e(e,t){var i=[],n=d.length,a=document.createElement("div");a.className="result",document.getElementById("results").appendChild(a),d.forEach(function(r){function l(){for(var e=0;e<N_ITER;e++){var t=Math.random()*width,i=Math.random()*height;points[e][0]=t,points[e][1]=i,points[e][2]=!1}}function d(){for(var e=0;e<N_ITER;e++)ctx.fillStyle=points[e][2]?"green":"red",ctx.fillRect(points[e][0],points[e][1],2,2)}function p(e){var o=e.target;i.push({ops:(N_ITER*m/(o.stats.mean+o.stats.moe)).toFixed(0),shapeType:r}),n--,a.innerHTML=u({result:i,name:t})}function f(e){console.log(e.message.message)}h.add("ZRender "+r,{fn:"for (var i = 0; i < N_ITER; i++) {\n points[i][2] = "+e+"(points[i][0], points[i][1]);\n }",setup:l,teardown:d,async:!0,onError:f,onStart:function(){zr.storage.delRoot();for(var e=0;m>e;e++){var t=o["make"+r](width,height);if(!t._pathProxy)t._pathProxy=new s,t.buildPath(t._pathProxy,t.style);c[e]=t,zr.addShape(t)}zr.refresh(),ctx.clearRect(0,0,width,height)},onComplete:p})})}var t=require("benchmark"),i=require("zrender"),n=require("etpl"),a=require("zrender/tool/area"),r=require("zrender/tool/util"),o=require("./shapes"),s=require("zrender/shape/util/PathProxy");window.zr=i.init(document.getElementById("main"));var l=document.getElementById("points");window.width=zr.getWidth(),window.height=zr.getHeight(),l.width=width,l.height=height,window.ctx=l.getContext("2d");var h=new t.Suite,d=["Circle","Line","Rectangle","Star","Sector","Heart","Cubic","Quadratic"];h.benchmarks=[],h.on("add",function(e){h.benchmarks.push(e.target)});var u=n.compile("<h3>${name}</h3> <table> <tr> <th>shape类型</th> <!-- for: ${result} as ${item} --> <th>${item.shapeType}</th> <!-- /for --> </tr> <tr> <td>op/s</td> <!-- for: ${result} as ${item} --> <td>${item.ops}</td> <!-- /for --> </tr> </table>"),c=[],m=20;window.N_ITER=2e3,window.points=[];for(var p=0;p<N_ITER;p++)points[p]=[0,0,!1];document.getElementById("run").addEventListener("click",function(){function t(e,t,i,n){var a;if("undefined"!=typeof n)n=(n||1)>>1,a=e.getImageData(t-n,i-n,n+n,n+n).data;else a=e.getImageData(t,i,1,1).data;for(var r=a.length;r--;)if(0!==a[r])return!0;return!1}window.mathMethod=function(e,t){for(var i=0;m>i;i++){var n=c[i];if(a.isInside(n,n.style,e,t))return!0}},window.buildPath=function(e,t){for(var i=0;m>i;i++){var n=c[i];if(ctx.beginPath(),n.buildPath(ctx,n.style),ctx.closePath(),ctx.isPointInPath(e,t))return!0}},window.jsInsidePath=function(e,t){for(var i=0;m>i;i++){var n=c[i];if(a.isInsidePath(n._pathProxy.pathCommands,n.style.lineWidth,n.style.brushType,e,t))return!0}},window.pixelMethod=function(e,i){for(var n=0;m>n;n++){var a=c[n],o=a.getRect(a.style),s=r.getPixelContext(),l=r.getPixelOffset();if(r.adjustCanvasSize(e,i),s.clearRect(o.x,o.y,o.width,o.height),s.beginPath(),a.brush(s,{style:a.style}),s.closePath(),t(s,e+l.x,i+l.y))return!0}},e("mathMethod","Math method"),e("buildPath","Native isPointInPath"),e("jsInsidePath","JS isPointInPath"),h.run()}),h.on("complete",function(){t.filter(h.benchmarks,"successful")})});
function() { var renderer = etpl.compile( text['default-cph'] ); expect(renderer()).toEqual(text[ 'expect-default-cph' ]); }
define(function (require) { var Emitter = require('../util/Emitter'); var etpl = require('etpl'); var tpl = require('./detail.tpl'); // 在使用etpl之前,需要提前编译模板 etpl.compile(tpl); var bind = require('../util/bind'); //首先我们要找到容器 var container = document.getElementById('detail'); var confirmDialog = require('../dialog/confirm'); // 然后声明view对象 var view = { // 绘制页面 draw: function (task, isedit, isnew) { // 是把任务设置为空,则清空 if (!task) { container.innerHTML = ''; return; } // 利用etpl的render方法绘制页面html // 将HTML塞进页面中 container.innerHTML = etpl.render('task', { isnew: isnew, isedit: isedit, title: task.title || '', finished: task.finished || false, date: task.date || '', content: task.content || '', list: task.content && task.content.split(/\r?\n/) || [] }); }, // 正在编辑中对话框 editConfirm: function (success) { confirmDialog.show('当前正在编辑任务,是否放弃?', success); } }; Emitter.mixin(view); // 给container委托编辑事件 bind(container, 'click', function (e) { // 阻止默认事件 e.preventDefault(); view.emit('edit'); }, '[data-role=edit]'); // 给container委托完成事件 bind(container, 'click', function (e) { // 阻止默认事件 e.preventDefault(); confirmDialog.show('完成的任务无法再次编辑,是否确认', function () { view.emit('finish'); }); }, '[data-role=finish]'); // 给container委托删除事件 bind(container, 'click', function (e) { // 阻止默认事件 e.preventDefault(); confirmDialog.show('删除的任务无法恢复,是否确认删除', function () { view.emit('delete'); }); }, '[data-role=delete]'); // 给container委托确认事件 bind(container, 'click', function (e) { // 阻止默认事件 e.preventDefault(); var title = document.getElementById('form-title').value || ''; var date = document.getElementById('form-date').value || ''; var content = document.getElementById('form-content').value || ''; var success = true; // 标题 if (!title || title.length > 20) { document.getElementById('form-title-error').innerHTML = title ? '任务标题不能超过20字' : '任务标题必需输入'; success = false; } else { document.getElementById('form-title-error').innerHTML = ''; } // 日期 if (!date) { document.getElementById('form-date-error').innerHTML = '任务日期必须输入!'; success = false; } else if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) { document.getElementById('form-date-error').innerHTML = '任务日期的格式应当为yyyy-MM-dd!'; success = false; } else { document.getElementById('form-date-error').innerHTML = ''; } // 内容 if (!content) { document.getElementById('form-content-error').innerHTML = '任务内容必须输入!'; success = false; } else if (content.length > 1000) { document.getElementById('form-content-error').innerHTML = '任务内容不能超过1000字!'; success = false; } else { document.getElementById('form-content-error').innerHTML = ''; } if (!success) { return; } confirmDialog.show('是否保存任务', function () { var title = document.getElementById('form-title').value || ''; var date = document.getElementById('form-date').value || ''; var content = document.getElementById('form-content').value || ''; view.emit('confirm', { title: title, date: date, content: content }); }); }, '[data-role=confirm]'); // 给container委托取消事件 bind(container, 'click', function (e) { // 阻止默认事件 e.preventDefault(); confirmDialog.show('是否放弃当前输入的内容', function () { view.emit('cancel'); }); }, '[data-role=cancel]'); return view; });
define(function (require) { var Component = require('./Component'); var zrUtil = require('zrender/tool/util'); var etpl = require('etpl'); var util = require('../util/util'); var bkgLog = require('../util/log'); var Sizzle = require('Sizzle'); var jsonp = require('../util/jsonp'); var Feedback = require('./Feedback'); var renderSearchResult = etpl.compile(require('text!../html/searchResult.html')); var renderHeaderBar = etpl.compile(require('text!../html/headerBar.html')); var config = require('../config'); var levels = config.levels; var share = config.share; var HeaderBar = function () { Component.call(this); this._graphCollapsed = true; var self = this; util.addEventListener(this.el, 'click', function (e) { self._dispatchClick(e); }); }; HeaderBar.prototype.type = 'HEADERBAR'; HeaderBar.prototype.initialize = function (kg, rawData) { var el = this.el; el.className = 'bkg-headerbar'; this._kgraph = kg; this.setData(rawData); // var graphMain = kg.getComponentByType('GRAPH'); // if (graphMain) { // this.setExplorePercent(graphMain.getExplorePercent()); // } // var sideBar = kg.getComponentByType('SIDEBAR'); // if (sideBar) { // sideBar.el.style.top = this.el.clientHeight + 'px'; // } var self = this; // search util.addEventListener(this._$inputArea, 'click', function (e) { e.cancelBubble = true; e.stopPropagation && e.stopPropagation(); self.filter(self._$input.value); }); var keyEvent = 'keydown'; var ua = navigator.userAgent.toLowerCase(); if (ua.indexOf("firefox") > 0 || ua.indexOf("msie") > 0) { keyEvent = 'keyup'; } util.addEventListener(this._$input, keyEvent, util.debounce(function (e) { var _$list = Sizzle('.bkg-search-list', this.el)[0]; var _$items = Sizzle('.bkg-search-list li', this.el); var _$active = Sizzle('.bkg-search-list .bkg-active', this.el)[0]; var index = 0; for (var i = 0, len = _$items.length; i < len; i++) { if (util.hasClass(_$items[i], 'bkg-active')) { index = i; break; } } switch(e.keyCode) { case 13: // enter var _$activeLink = Sizzle('.bkg-search-list .bkg-active a', this.el)[0]; if (_$activeLink) { window.open(_$activeLink.getAttribute('href')); } break; case 38: //up arrow _$active && util.removeClass(_$active, 'bkg-active'); index--; if (index < 0) { index = len - 1; } util.addClass(_$items[index], 'bkg-active'); break; case 40: //down arrow _$active && util.removeClass(_$active, 'bkg-active'); index++; if (index > len - 1) { index = 0; } util.addClass(_$items[index], 'bkg-active'); break; default: self.filter(self._$input.value); } }, 200)); util.addEventListener(Sizzle('body')[0], 'click', function (e) { var target = e.target || e.srcElement; var current = target; while (current && current.nodeName.toLowerCase() !== 'a') { current = current.parentNode; } if (!current) { self._$input.value = ''; self._$searchResult.innerHTML = ''; util.removeClass(self._$share, 'bkg-share-btn-active'); util.addClass(self._$shareList, 'hidden'); setTimeout(function () { util.addClass(self._$shareList, 'bkg-hidden'); }, 300); } }); util.addEventListener(this._$searchResult, 'mouseover', function (e) { var target = e.target || e.srcElement; var current = target; while (current && current.nodeName.toLowerCase() !== 'li') { current = current.parentNode; } var _$active = Sizzle('.bkg-search-list .bkg-active', this.el)[0]; if (_$active && current !== _$active) { util.removeClass(_$active, 'bkg-active'); util.addClass(current, 'bkg-active'); } }); // share util.addEventListener(this._$share, 'click', function (e) { e.cancelBubble = true; e.stopPropagation && e.stopPropagation(); if (util.hasClass(self._$shareList, 'hidden')) { util.removeClass(self._$shareList, 'bkg-hidden'); setTimeout(function () { util.removeClass(self._$shareList, 'hidden'); }, 100); util.addClass(self._$share, 'bkg-share-btn-active'); } else { util.addClass(self._$shareList, 'hidden'); setTimeout(function () { util.addClass(self._$shareList, 'bkg-hidden'); }, 300); util.removeClass(self._$share, 'bkg-share-btn-active'); } }); var $wbShareBtn = Sizzle('.bkg-share', this.el); util.addEventListener(this._$shareList, 'click', function (e) { var target = e.target || e.srcElement; if (target.nodeName.toLowerCase() == 'li') { var type = target.getAttribute('data-type'); switch (type) { case 'weibo': self.weiboShare(e); break; } } }); }; HeaderBar.prototype.setData = function (data) { // var mainEntity = data.mainEntity; // for (var i = 0; i < levels.length - 1; i++) { // levels[i].interval = levels[i + 1].position - levels[i].position; // } this.render({ name: document.title, levels: levels }); }; HeaderBar.prototype.render = function (data) { this.el.innerHTML = renderHeaderBar(data); this._$levels = Sizzle('.bkg-level', this.el); this._$inputArea = Sizzle('.bkg-search-input', this.el)[0]; this._$input = Sizzle('.bkg-search-input input', this.el)[0]; this._$searchResult = Sizzle('.bkg-search-result', this.el)[0]; this._$share = Sizzle('.bkg-share', this.el)[0]; this._$shareList = Sizzle('.bkg-share-area', this.el)[0]; this._$feedback = Sizzle('.bkg-feedback', this.el)[0]; this._feedback = new Feedback(this._$feedback); }; HeaderBar.prototype.setExplorePercent = function (percent) { percent = Math.max(percent * 100, 1); Sizzle('.bkg-explore-percent-bar-inner', this.el)[0].style.width = percent + '%'; for (var i = 0; i < levels.length; i++) { util.removeClass(this._$levels[i], 'bkg-active'); } for (var i = 0; i < levels.length; i++) { if (levels[i].position <= percent && (!levels[i+1] || levels[i + 1].position > percent)) { util.addClass(this._$levels[i], 'bkg-active'); } } } HeaderBar.prototype.filter = function (name) { var self = this; var renderData = {}; var nodata = ''; if (name) { var url = this._kgraph.getDetailAPI(); jsonp(url, { act: 'tpuser', mt: 'use', 'ver': 'v1', q: name }, 'callback', function (data) { if (config.isPlat) { return; } renderData = { entities: data.data || [], name: name }; self._$searchResult.innerHTML = renderSearchResult(renderData); if (!data.data) { nodata = 'nodata'; } bkgLog({ type: 'zhishitupusearch', target: name, area: 'headerbar', extend: nodata }); }); } else { renderData = { interests: this._kgraph.getRawData() && this._kgraph.getRawData().interests, name: name }; this._$searchResult.innerHTML = renderSearchResult(renderData); } }; HeaderBar.prototype.weiboShare = function (e) { var _$levels = this._$levels; for (var idx = 0, len = _$levels.length; idx < len; idx++) { if (Sizzle.matchesSelector(_$levels[idx], '.bkg-active')) { break; } } if(idx < 0) return; var randomIndex = Math.floor(Math.random() * share.length + 1) - 1; var shareContent = share[randomIndex].replace('{name}', document.title.substring(0, document.title.indexOf(' '))); var _param = { url: document.URL, appkey: '', ralateUid: '', //关联用户的id,自动@ title: shareContent, pic: '', language: 'zh_cn' } var paramArr = []; for (var i in _param) { if (_param[i]) { paramArr.push(i + '=' + encodeURIComponent(_param[i])); } } var url = "http://service.weibo.com/share/share.php?" + paramArr.join('&'); var height = 100; var width = 400; var left = (screen.width - width) / 2; var top = (screen.height - height) / 2; window.open(url, 'newwindow', 'height=' + height + ',width=' + width + ',left=' + left + ',top=' + top); // Log weibo level bkgLog({ type: 'zhishitupuweibo', target: JSON.stringify(shareContent) }); }; HeaderBar.prototype._dispatchClick = function (e) { var target = e.target || e.srcElement; var current = target; while (current && current.nodeName.toLowerCase() !== 'a') { current = current.parentNode; } var fromid = this._kgraph.getRawData() && this._kgraph.getRawData().mainEntity.id; if (current) { var linkArea = current.getAttribute('data-area'); bkgLog({ type: 'zhishitupulink', target: [ fromid, current.getAttribute('title'), current.getAttribute('href') ].join(','), area: 'headerbar-' + linkArea }); } }; HeaderBar.prototype.resize = function (w, h) { this._feedback && this._feedback.resize(w, h); }; zrUtil.inherits(HeaderBar, Component); return HeaderBar; });
define(function (require) { var _ = require('underscore'); var fc = require('fc-core'); var etpl = require('etpl'); var Control = require('./Control'); var ui = require('./main'); var lib = require('./lib'); /** * 默认配置 * * @type {Object} * @const */ var DEFAULT_OPTION = { fakePausePercent: '85%', fakeProcessTime: 20000 }; /** * 事件名 * @type {Object.<string, string>} * @const */ var EVENT_NAMES = { /** * 进度条已经达到预定的比例,参见DEFAULT_OPTION.fakePausePercent */ TARGET_REACHED_EVENT: 'targetreached', /** * 暂停等待事件,此时除非发生外界干预,进度条不再前进 */ PAUSE_EVENT: 'progressbarpaused', /** * 结束绘制完成事件 */ FINISH_EVENT: 'progressbarfinished', /** * 进度条修改位置绘制完成事件 */ CHANGE_EVENT: 'progressbarchanged' }; /** * 不同阶段的事件关键字定义,将不同阶段映射到EVENT_NAMES的key上 * @type {Object.<string, string>} */ var STAGE_EVENT = { TARGET_REACHED: 'TARGET_REACHED_EVENT', PAUSED: 'PAUSE_EVENT', FINISHED: 'FINISH_EVENT', CHANGED: 'CHANGE_EVENT' }; /** * 生成进度条id的前缀 * * @type {string} * @const */ var ID_PREFIX = 'view-progress-bar-'; /** * 默认的变化速度 * @type {string} * @cosnt */ var DEFAULT_CHANGE_SPEED = 'normal'; /** * 默认加载完成后的宽度比例 * @type {string} * @const */ var DEFAULT_FINISH_PERCENT = '100%'; /** * 模板 * * TODO (mahaina) nirvana加载tpl文件跨域问题解决后需要移出至独立文件 * @type {string} */ var TPL = '' + '<!-- target: library-framework-ui-progress-bar -->' + '<div class="${mainClass}">' + '<div class="${chartClass}">' + '</div>' + '</div>'; etpl.compile(TPL); var proto = {}; /** * ProgressBar 进度条 * 进度条会按照container的宽高自适应 * * @param {Object} option ProgressBar配置参数 * @param {string=} option.id ProgressBar的id * @param {number=} option.fakePausePercent 模拟等待位置,百分比的分子,100以内 * @param {number=} option.fakeProcessTime 模拟处理时间,单位毫秒 * * 对外暴露的调用接口 * start 进度条开始 * pause 暂停在当前位置 * changeTo 改变进度至某一位置 * finish 加载结束 * * 暴露事件 * 参考常量EVENT_NAMES定义 * * @constructor */ proto.constructor = function (option) { option = _.deepEextend({}, DEFAULT_OPTION, option); option.id = option.id || ID_PREFIX + fc.util.guid(); Control.apply(this, arguments); }; /** * 控件类型,始终为`"FcProgressBar"` * * @type {string} * @readonly * @override */ proto.type = 'FcProgressBar'; /** * 初始化,将模板插入html中 * * @param {Object} options 初始化参数 * @protected * @override */ proto.initOptions = function (options) { var properties = _.deepExtend({}, DEFAULT_OPTION, options); this.setProperties(properties); }; /** * 创建主元素,默认使用'<div>'元素 * * @return {HtmlElement} 主元素 * @protected * @override */ proto.createMain = function () { return document.createElement('div'); }; /** * 初始化DOM结构 * * @protected * @override */ proto.initStructure = function () { // 子元素挂在皮肤class var helper = this.helper; var mainClass = helper.getPartClasses('main').join(' '); var chartClass = helper.getPartClasses('chart').join(' '); this.main.innerHTML = etpl.render( 'library-framework-ui-progress-bar', { mainClass: mainClass, chartClass: chartClass } ); /** * 进度条 * @type {jQuery} * @private */ this._progressBar = lib.find(this.main, '.ui-progressbar-chart'); }; /** * 动画实现 * @param {number} width 进度条宽 * @param {string|number} speed 动画速度 * @param {Function=} callback 回调函数 * @private */ proto._animate = function (width, speed, callback) { var style = {width: width}; var progressBar = this._progressBar; // 避免之前动画还未完成,先调用stop progressBar.stop(); if (callback) { progressBar.animate(style, speed, callback); } else { progressBar.animate(style, speed); } }; /** * 动画完成后的回调处理 * @param {string} type 事件key * @return {Function} 回调函数 * @private */ proto._animateCallback = function (type) { var me = this; return function () { me._fireEvent(type); }; }; /** * fire事件 * @param {string} type 事件类型 * @private */ proto._fireEvent = function (type) { var progressBar = this._progressBar; var currentWidth = progressBar.width(); var eventData = {currentWidth: currentWidth}; var eventName = EVENT_NAMES[type]; this.fire(eventName, {data: eventData}); }; /** * ProgressBar进度条开始滚动 */ proto.start = function () { var pausePercent = this.fakePausePercent; this._animate( pausePercent, this.fakeProcessTime, this._animateCallback(STAGE_EVENT.TARGET_REACHED) ); }; /** * ProgressBar暂停在当前位置 */ proto.pause = function () { this._progressBar.stop(); this._fireEvent(STAGE_EVENT.PAUSED); }; /** * ProgressBar结束,完成全部进度 */ proto.finish = function () { this._animate( DEFAULT_FINISH_PERCENT, DEFAULT_CHANGE_SPEED, this._animateCallback(STAGE_EVENT.FINISHED) ); }; /** * 将进度修改为某一宽度 * @param {number} percentWidth 设定的目标百分比 * @param {string|number=} speed 动画速度,默认参见DEFAULT_CHANGE_SPEED * string的可选项为'slow', 'fast', 'normal';number单位为毫秒 */ proto.changeTo = function (percentWidth, speed) { speed = speed || DEFAULT_CHANGE_SPEED; this._animate( percentWidth, speed, this._animateCallback(STAGE_EVENT.CHANGED) ); }; var ProgressBar = fc.oo.derive(Control, proto); ui.register(ProgressBar); return ProgressBar; });
function (require) { var etpl = require( 'etpl' ); var readText = require( 'readTextSync' ); var text = readText( 'spec/variableSubstitution.text.html' ); etpl.compile( text['tpl'] ); var data = { name: text['name'], address: text['address'], info: { repos: text['info-repos'], contributor: { name: text['info-contributor-name'], email: text['info-contributor-email'] } } }; data.contributors = [data.info.contributor]; describe('Variable Substitution', function() { it( 'should encode html by default', function() { expect(etpl.getRenderer('variableSubstitution-normal')(data)) .toEqual(text['expect-normal']); } ); it( 'should substitute raw string when use raw filter', function() { expect(etpl.getRenderer('variableSubstitution-raw')(data)) .toEqual(text['expect-raw']); } ); it( 'should substitute correctly if has more than 1 filters', function() { expect(etpl.getRenderer('variableSubstitution-filters')(data)) .toEqual(text['expect-filters']); } ); it( 'should substitute correctly when many variables and filters mixed', function() { expect(etpl.getRenderer('variableSubstitution-mix')(data)) .toEqual(text['expect-mix']); } ); it( 'can use property accessor "."', function() { expect(etpl.getRenderer('variableSubstitution-property-accessor')(data)) .toEqual(text['expect-property-accessor']); } ); it( 'can use property accessor "[]"', function() { expect(etpl.getRenderer('variableSubstitution-property-accessor2')(data)) .toEqual(text['expect-property-accessor2']); } ); }); }
define(function (require) { var etpl = require('etpl'); var ui = require('./main'); var _ = require('underscore'); var fc = require('fc-core'); var lib = require('./lib'); var eventTarget = require('mini-event/EventTarget'); require('./FcProgressBar'); /** * 随机生成id的前缀 * * @type {string} * @const */ var ID_PREFIX = 'view-loading-'; /** * 图片区域样式class名称前缀 * * @type {string} * @const */ var IMG_CLASS_PREFIX = ID_PREFIX + 'img-'; /** * 进度条控件id的后缀 * * @type {string} * @const */ var PROGRESS_BAR_ID_SUFFIX = '-progress-bar'; /** * 进度条结束事件 * * @type {string} * @const */ var PROGRESS_BAR_FINISH_EVENT = 'progressbarfinished'; /** * loading的类型 * * @type {Object.<string, number>} * @const */ var LOADING_TYPE = { /** * 普通类型,同时显示标准gif和文字 */ NORMAL: 0, /** * 进度条类型,同时显示进度条和文字 */ PROGRESS: 1, /** * 仅文字提示 */ TEXT: 2 }; /** * loading类型的状态反向,值 -> key * * @type {Object.<number, string>} * @const */ var LOADING_TYPE_KEY = {}; (function () { for (var key in LOADING_TYPE) { if (LOADING_TYPE.hasOwnProperty(key)) { LOADING_TYPE_KEY[LOADING_TYPE[key]] = key.toLowerCase(); } } })(); /** * loading事件 * * @type {string} * @const */ var LOADING_EVENT = { SHOWED: 'showed', DISPOSING: 'disposing', DISPOSED: 'disposed' }; /** * 默认配置项 * * @type {Object} * @const */ var DEFAULT_OPTION = { type: LOADING_TYPE_KEY[LOADING_TYPE.NORMAL], // 加载提示话术 loadingText: '正在加载中...' }; /** * 模板 * * TODO (mahaina) nirvana加载tpl文件跨域问题解决后需要移出至独立文件 * @type {string} */ var TPL = '' + '<!-- target: library-framework-view-loading -->' + '<div id="${id}" class="view-loading hide">' + '<!-- if: ${type} !== "TextOnly" -->' + '<div class="view-loading-img ${imgClass}">' + '<!-- if: ${type} === "progress" -->' + '<div data-ui-id="${progressBarId}" data-ui-type="FcProgressBar"></div>' + '<!-- /if -->' + '</div>' + '<!-- /if -->' + '<span class="view-loading-text">${loadingText}</span>' + '</div>'; etpl.compile(TPL); /** * 区域缓存的全部loading实例,格式如下 * { * 传入的container: 生成的loading instance * } * * @type {Object} */ var loadingCache = {}; var proto = {}; /** * Loading控件 * * @param {Object} option Loading配置参数 * @param {string} option.container 容器 * @param {number=} option.id loading的id * 不传时会自动生成唯一ID,(除非特殊场景)不推荐传入 * @param {string=} option.type loading类型,有'normal|progress|text' * 'normal' 普通loading图片和话术提示 * 'progress' 进度条类型 * 'text' 仅文本 * @param {string=} option.loadingText 加载话术 * * 对外暴露的调用接口 * init 显示loading * hide 隐藏并销毁loading * dispose 销毁loading * * 静态接口 * init 一次性生成多个Loading实例并显示它们 * done 一次性结束并销毁所有Loading实例 * * 对外fire事件 * show 已显示loading * disposing 即将销毁loading * * @constructor */ proto.constructor = function (option) { if (!option || !option.container) { throw new Error('Loading container is needed.'); } /** * Loading的配置项 * * @type {Object} * @private */ this._option = this._getOption(option); this._initHtml(); }; /** * 获得配置参数 * * @param {Object} option 调用方传入的参数 * @return {Object} 处理后的参数 * @private */ proto._getOption = function (option) { option.containerStr = option.container; option.container = lib.find(document, option.container); option = _.extend(true, {}, DEFAULT_OPTION, option); option.id = option.id || (ID_PREFIX + fc.util.guid()); // 进度条esui的id option.progressBarId = option.id + PROGRESS_BAR_ID_SUFFIX; return option; }; /** * 初始化,将模板插入html中 * * @private */ proto._initHtml = function () { var option = this._option; var imgClass = this.getImgClass(); var tplHtml = etpl.render( 'library-framework-view-loading', { id: option.id, type: option.type, loadingText: option.loadingText, imgClass: imgClass, progressBarId: option.progressBarId } ); var container = option.container; container.innerHTML = tplHtml; this._initImg(); }; /** * 获得loading的图片区域样式class名称 * * @return {string} */ proto.getImgClass = function () { var option = this._option; var type = option.type; return IMG_CLASS_PREFIX + type.toLowerCase(); }; /** * 初始化加载提示图片 * * @private */ proto._initImg = function () { var option = this._option; var type = option.type; var progressType = LOADING_TYPE_KEY[LOADING_TYPE.PROGRESS]; if (type === progressType) { this._initEsui(); /** * 进度条引用 * @type {Control} * @private */ this._progressBar = ui.getSafely(option.progressBarId); } }; /** * 切换生命周期阶段 * * @param {string} stage 切换的目标阶段 * @private */ proto._changeToStage = function (stage) { this.fire(stage); }; /** * 初始化进度条控件 * * @private */ proto._initEsui = function () { var container = this._option.container; ui.init(container); }; /** * 显示loading */ proto.init = function () { var option = this._option; lib.removeClass(lib.find('#' + option.id), 'hide'); var progressBar = this._progressBar; // 如果是进度条形式,调用进度条的开始方法 if (progressBar) { progressBar.start(); } this._changeToStage(LOADING_EVENT.SHOWED); }; /** * loading结束 */ proto.done = function () { var me = this; var progressBar = me._progressBar; // 如果是进度条形式,调用进度条的开始方法 if (progressBar) { progressBar.on(PROGRESS_BAR_FINISH_EVENT, function () { me.dispose(); }); progressBar.finish(); } else { me.dispose(); } }; /** * 销毁loading */ proto.dispose = function () { var option = this._option; this._changeToStage(LOADING_EVENT.DISPOSING); option.container.innerHTML = ''; // 如果在cache中也需要删除 var cachedInstance = loadingCache[option.containerStr]; if (cachedInstance) { delete loadingCache[option.containerStr]; } this._changeToStage(LOADING_EVENT.DISPOSED); }; var Loading = fc.oo.derive(eventTarget, proto); /** * 区域缓存的全部loading实例,格式如下 * { * 传入的container: 生成的loading instance * } * * @type {Object} */ Loading.loadingCache = loadingCache; /** * Loading静态工具方法,一次生成多个Loading实例,并依次显示它们 * * @param {Array.<Object>} options 多个Loading实例的生成数组,内容参见Loading构造函数说明 * 最简易使用方法为传入所有需要显示Loading位置的container组成的数组 * @return {Object.<string, Object>} 返回当前所有loading实例 */ Loading.init = function (options) { if (!options || !options.length) { throw new Error( 'At least one option(which containes `container`) is needed' ); } _.each(options, function (option, key) { var container = option.container; var loadingInstance = new Loading(option); if (loadingInstance) { loadingCache[container] = loadingInstance; loadingInstance.init(); } }); return loadingCache; }; /** * Loading静态工具方法,一次关闭并销毁若干或所有Loading实例 * @param {Array.<string>=} containers 需要结束Loading的所有区域的container数组 * 可选,不传入时结束所有Loading */ Loading.done = function (containers) { if (containers && containers.length) { _.each(containers, function (container) { var loadingInstance = loadingCache[container]; if (loadingInstance) { loadingInstance.done(); } }); } else { _.each(loadingCache, function (loadingInstance) { loadingInstance.done(); }); } }; return Loading; });
function (require) { var etpl = require( 'etpl' ); var readText = require( 'readTextSync' ); var text = readText( 'spec/variableSubstitution.text.html' ); etpl.addFilter( 'slice', function (source, begin, end) { return source.slice( begin, end ); } ); etpl.addFilter( 'dateFormat', function (source) { return source.getFullYear() + '-' + (source.getMonth() + 1) + '-' + source.getDate(); } ); etpl.compile( text['tpl'] ); var data = { name: text['name'], address: text['address'], info: { repos: text['info-repos'], contributor: { name: text['info-contributor-name'], email: text['info-contributor-email'] } }, first: parseInt( text.first, 10 ), end: parseInt( text.end, 10 ), date: eval( text.date ) }; data.contributors = [data.info.contributor]; describe('Variable Substitution', function() { it( 'should encode html by default', function() { expect(etpl.getRenderer('variableSubstitution-normal')(data)) .toEqual(text['expect-normal']); } ); it( 'should substitute raw string when use raw filter', function() { expect(etpl.getRenderer('variableSubstitution-raw')(data)) .toEqual(text['expect-raw']); } ); it( 'should substitute correctly if has more than 1 filters', function() { expect(etpl.getRenderer('variableSubstitution-filters')(data)) .toEqual(text['expect-filters']); } ); it( 'should use raw value when prefix "*"', function() { expect(etpl.getRenderer('variableSubstitution-rawvalue')(data)) .toEqual(text['expect-rawvalue']); } ); it( 'can accept data in filter', function() { expect(etpl.getRenderer('variableSubstitution-filter-arg')(data)) .toEqual(text['expect-filter-arg']); } ); it( 'should substitute correctly when many variables and filters mixed', function() { expect(etpl.getRenderer('variableSubstitution-mix')(data)) .toEqual(text['expect-mix']); } ); it( 'can use property accessor "."', function() { expect(etpl.getRenderer('variableSubstitution-property-accessor')(data)) .toEqual(text['expect-property-accessor']); } ); it( 'can use property accessor "[]"', function() { expect(etpl.getRenderer('variableSubstitution-property-accessor2')(data)) .toEqual(text['expect-property-accessor2']); } ); }); }
exports.render = function (context, tpl) { var render = template.compile(tpl); return render(context); };