D3에서 긴 텍스트에 대한 처리

이전 포스팅의 텍스트 줄바꿈 처리는 모든 브라우져에서 동작 하지 않는다. 확인 해본 결과 Firefox에서는 동작 하지만, 많이 사용되는 Chrome에서는 동작 하지 않는다.

모든 브라우져에서 동작하기 위한 코드를 찾아본 결과 Wrapping Long Labels을 발견 할 수 있었다.

위의 코드에서 wrap을 해주는 매소드에 보면 text 태그 하단에 들어가는 tspan이라는 태그를 발견 하였는데, 이를 이용하여 여러 라인 처리를 하는 것을 확인했다. 이를 활용하면 긴 문장에 대한 여러 방법으로 처리가 가능 하다.

function wrap(text, width) {
  text.each(function() {
    var text = d3.select(this),
        words = text.text().split(/\s+/).reverse(),
        word,
        line = [],
        lineNumber = 0,
        lineHeight = 1.1, // ems
        y = text.attr("y"),
        dy = parseFloat(text.attr("dy")),
        tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
    while (word = words.pop()) {
      line.push(word);
      tspan.text(line.join(" "));
      if (tspan.node().getComputedTextLength() > width) {
        line.pop();
        tspan.text(line.join(" "));
        line = [word];
        tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
      }
    }
  });
}

SVG tspan element을 보면 tspan 요소는 SVG에서 여러 텍스트를 그리는데 사용되는 테그로 설명 된다. 해당 태그를 이용하면 첨부된 소스를 사용하지 않고도 여러 라인의 문자열 처리가 가능하다.

라이선스 관련

Released under the GNU General Public License, version 3.

참고 자료

  1. Wrapping Long Labels
  2. SVG tspan element


Posted by lahuman

[JAVASCRIPT] - 주소창의 parameter 제거

보통은 주소창에 parameter 값이 다음과 같이 표출된다.

https://lahuman.github.io/posts/?lang=ko

이때 해당 주소에서 parameter 값만 제거 하고 싶을 경우 다음의 스크립트를 이용하면 간단히 처리 할 수 있다.

history.replaceState({}, null, location.pathname);

parameter가 제거된 값은 다음과 같다.

https://lahuman.github.io/posts/

Posted by lahuman

Array.prototype.reduce VS for loop



Array.prototype.reduce Syntax


  arr.reduce(callback [, initialValue] ) 

  


  

[1, 2, 3].reduce(function(previousValue, currentValue, index, array){
      ....
      return currentValue
  }, '');
  • previousValue : initialValue(사용자가 정의한 초기값) 혹은 currentValue의 이전 index 값 ( arr[index-1] );
    처음 실행시 초기값이 있으면 초기값이 전달 되며, 초기값이 없을 경우 배열의 0번째 index 배열값이 전달 된다.
    이후 항상 currentValue의 이전 index 배열값이 전달 된다.   
  • currentValue : 배열의 현재 값
  • index : 현재 배열의 인덱스
  • array : reduce method가 호출된 배열
  • initialValue : 초기값 위에서는 '' 으로 되어 있음. 



Array.prototype.reduce Sample

var array = [1, 5, 10, 15, 20];
/* 초기값(initialValue)이 없을 때의 Array.prototype.reduce의 파라미터 값 확인 */
array.reduce(function(previousValue, currentValue, index, array) {
  console.log("index:"+index + ", previousValue:" + previousValue +", currentValue:"+currentValue +", array:" + array);
  return currentValue;
});

/* 초기값(initialValue)이 없을 때의 Array.prototype.reduce의 파라미터 값 확인 */
array.reduce(function(previousValue, currentValue, index) {
  console.log("index:"+index + ", previousValue:" + previousValue +", currentValue:"+currentValue );
    return currentValue;
}, undefined);


/* forEach 는 return 이 없다. */
array.forEach(function(element, index, array){
   console.log(element + " :: " + index + " :: " + array);
});

/* 일반적인 for loop */
var sum = 0;
for(var i=0; i < array.length; i++) {
  sum += array[i];
}
console.log(sum);


/* 초기값 (initialValue) 0을 준 경우 */
sum = 0;
sum = array.reduce(function(previousValue, currentValue, index) {
    return sum += currentValue;
}, 0);
console.log(sum);

/* 초기값 (initialValue)을 주지 않은 경우 */
sum = 0;
sum = array.reduce(function(previousValue, currentValue, index) {
    return sum += currentValue;
}, 0);
console.log(sum);



참고자료

 

 Understand Javascript Array Reduce in 1 Minute

 https://www.airpair.com/javascript/javascript-array-reduce#javascript-reducing-vs-looping


 Mozilla Docs for Array.prototype.reduce

 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce


 Facebook >> 생활코딩

 https://www.facebook.com/groups/codingeverybody/permalink/1058801940827008/



Posted by jabsiri

웹에서 간트 차트를 만들수 있는 쉽고 간단한 라이브러리를 추천 합니다.






사용 법은 다음과 같습니다.

<link rel="stylesheet" type="text/css" href="jsgantt.css" />
<script language="javascript" src="jsgantt.js"></script>
<div style="position:relative" class="gantt" id="GanttChartDIV"></div>
<script>

  var g = new JSGantt.GanttChart('g',document.getElementById('GanttChartDIV'), 'day');
  g.setShowRes(1); // Show/Hide Responsible (0/1)
  g.setShowDur(1); // Show/Hide Duration (0/1)
  g.setShowComp(1); // Show/Hide % Complete(0/1)
  g.setCaptionType('Resource');  // Set to Show Caption

  if( g ) {

    g.AddTaskItem(new JSGantt.TaskItem(1,   'Define Chart API',     '',          '',          'ff0000', 'http://help.com', 0, 'Brian',     0, 1, 0, 1));
    g.AddTaskItem(new JSGantt.TaskItem(11,  'Chart Object',         '2/20/2008', '2/20/2008', 'ff00ff', 'http://www.yahoo.com', 1, 'Shlomy',  100, 0, 1, 1));
    g.AddTaskItem(new JSGantt.TaskItem(12,  'Task Objects',         '',          '',          '00ff00', '', 0, 'Shlomy',   40, 1, 1, 1));
    g.AddTaskItem(new JSGantt.TaskItem(121, 'Constructor Proc',     '2/21/2008', '3/9/2008',  '00ffff', 'http://www.yahoo.com', 0, 'Brian T.', 60, 0, 12, 1));
    g.AddTaskItem(new JSGantt.TaskItem(122, 'Task Variables',       '3/6/2008',  '3/11/2008', 'ff0000', 'http://help.com', 0, '',         60, 0, 12, 1,121));
    g.AddTaskItem(new JSGantt.TaskItem(123, 'Task Functions',       '3/9/2008',  '3/29/2008', 'ff0000', 'http://help.com', 0, 'Anyone',   60, 0, 12, 1, 0, 'This is another caption'));
    g.AddTaskItem(new JSGantt.TaskItem(2,   'Create HTML Shell',    '3/24/2008', '3/25/2008', 'ffff00', 'http://help.com', 0, 'Brian',    20, 0, 0, 1,122));
    g.AddTaskItem(new JSGantt.TaskItem(3,   'Code Javascript',      '',          '',          'ff0000', 'http://help.com', 0, 'Brian',     0, 1, 0, 1 ));
    g.AddTaskItem(new JSGantt.TaskItem(31,  'Define Variables',     '2/25/2008', '3/17/2008', 'ff00ff', 'http://help.com', 0, 'Brian',    30, 0, 3, 1, ,'Caption 1'));
    g.AddTaskItem(new JSGantt.TaskItem(32,  'Calculate Chart Size', '3/15/2008', '3/24/2008', '00ff00', 'http://help.com', 0, 'Shlomy',   40, 0, 3, 1));
    g.AddTaskItem(new JSGantt.TaskItem(33,  'Draw Taks Items',      '',          '',          '00ff00', 'http://help.com', 0, 'Someone',  40, 1, 3, 1));
    g.AddTaskItem(new JSGantt.TaskItem(332, 'Task Label Table',     '3/6/2008',  '3/11/2008', '0000ff', 'http://help.com', 0, 'Brian',    60, 0, 33, 1));
    g.AddTaskItem(new JSGantt.TaskItem(333, 'Task Scrolling Grid',  '3/9/2008',  '3/20/2008', '0000ff', 'http://help.com', 0, 'Brian',    60, 0, 33, 1));
    g.AddTaskItem(new JSGantt.TaskItem(34,  'Draw Task Bars',       '',          '',          '990000', 'http://help.com', 0, 'Anybody',  60, 1, 3, 1));
    g.AddTaskItem(new JSGantt.TaskItem(341, 'Loop each Task',       '3/26/2008', '4/11/2008', 'ff0000', 'http://help.com', 0, 'Brian',    60, 0, 34, 1, "332,333"));
    g.AddTaskItem(new JSGantt.TaskItem(342, 'Calculate Start/Stop', '4/12/2008', '5/18/2008', 'ff6666', 'http://help.com', 0, 'Brian',    60, 0, 34, 1));
    g.AddTaskItem(new JSGantt.TaskItem(343, 'Draw Task Div',        '5/13/2008', '5/17/2008', 'ff0000', 'http://help.com', 0, 'Brian',    60, 0, 34, 1));
    g.AddTaskItem(new JSGantt.TaskItem(344, 'Draw Completion Div',  '5/17/2008', '6/04/2008', 'ff0000', 'http://help.com', 0, 'Brian',    60, 0, 34, 1));
    g.AddTaskItem(new JSGantt.TaskItem(35,  'Make Updates',         '10/17/2008','12/04/2008','f600f6', 'http://help.com', 0, 'Brian',    30, 0, 3,  1));



    g.Draw();	
    g.DrawDependencies();


  }
  else
  {
    alert("not defined");
  }

</script>

주요 포인트 :

1. 표출 하려는 div 밑에 꼭 "var g = new JSGantt.GanttChart('g',document.getElementById('GanttChartDIV'), 'day');" 이부분을 선언 하셔야 동작 합니다.

2. jsGantt는 다시 그리기를 지원 하지 않습니다. 화면 재로딩을 이용하시기를 추천 드립니다.

3. 라인이 조금씩 깨집니다. 길어질 경우 보기 안좋을 수 있습니다.



URL : http://www.jsgantt.com/

DOWNLOAD : https://code.google.com/p/jsgantt/

Posted by lahuman





requirejs 는 어디에 쓰는 물건인가.


requirejs 홈페이지에 가면 "RequireJS is a JavaScript file and module loader" 라고 제일 첫 줄에 나온다.

"자바스크립트 파일과 모듈 로더다."


아직 뭔지 와닫지 않는다..


모듈이란. 

일반적으로 컴퓨터 분야에서의 모듈은 "독립되어 있는 하나의 소프트웨어 또는 하드웨어 단위를 지칭하는데 사용된다. "

라고 네이버 백과사전에 나와있다.


조금도 쉽게 말하면 JavaScript에서 jquery도 모듈이고, util성으로 만든 function들의 모음 js도 하나의 모듈로 볼수 있다.

requirejs는 이런 모듈을 로딩하는 역활을 하는것이다.

자 그럼 requirejs를 사용하기 위해서는 JavaScript 모듈화 작업이 필요하다.


모듈화.

JavaScript 모듈화 및 로더 작업을 할수 있는 방법으로 CommonJS 그룹과 AMD 그룹에서 명세를 정의해 놓고 있다. 


CommonJS는 서버 사이드 JavaScript에서의 모듈정의와 모듈로드에 초점이 맞춰저 있고 ( 대표 적인예 node.js) 

AMD(Asynchronous module definition) 는 브라우저 환경 ( 네트워크를 통해 모듈을 받아서 처리해야하는 ) 에서 모듈 정의와 모듈 로드에 초점이 맞춰저 있다. ( 대표적인 예 : require.js )

* 물론 둘다 서버사이드와 브라우저 환경에서 모듈화를 정의하고 사용할수 있지만 각자 특화된 부분이 있다는 것이다.


이 둘의 공통점은 모듈화에 있는데 이는 CommonJS에서 AMD가 파생된 그룹이기 때문이다.



RequireJS

그럼 제일 첫 부분에 적었던  "RequireJS is a JavaScript file and module loader" 부분이 약간은 이해가 될지 모르겠다.

RequireJS는 AMD모듈 정의서에 따라 개발된 대표적인 JavaScript 로더 중 하나로 AMD 모듈 로딩 표준을 따르기에 기본적으로 모든 모듈이 비동기적이다.

또한 javascript 모듈의 의존관계등의 관리도 쉽게 할수 있게도와준다.



참고자료


[1] NAVER helloworld - NHN 모바일Ajax팀 손병대

JavaScript 표준을 위한 움직임: CommonJS와 AMD 

http://helloworld.naver.com/helloworld/12864


[2] Nonblock Blog - Hanghee Yi

RequireJS – JavaScript 파일 및 모듈 로더 

http://blog.javarouka.me/2013/04/requirejs-javascript.html



Posted by jabsiri

Tag Cloud 기술을 간단하게 사용할 수 있는 Jquery plugin 을 소개 합니다.



사용법은 간단 합니다.



 /*!
       * Create an array of word objects, each representing a word in the cloud
       */
      var word_array = [
          {text: "Lorem", weight: 15},
          {text: "Ipsum", weight: 9, link: "http://jquery.com/"},
          {text: "Dolor", weight: 6, html: {title: "I can haz any html attribute"}},
          {text: "Sit", weight: 7},
          {text: "Amet", weight: 5}
          // ...as many words as you want
      ];

      $(function() {
        // When DOM is ready, select the container element and call the jQCloud method, passing the array of words as the first argument.
        $("#example").jQCloud(word_array);
      });



과 같이 하면, 


다음과 같은 UI가 표출 됩니다.



데이터만 잘 만들면 꽤나 유용한 기능을 제공 할 것이라 판단 됩니다.

참고로 위에 소스를 보면 아시듯이 TITLE과 LINK 기능을 지원 합니다.




샘플 : http://www.lucaongaro.eu/demos/jqcloud/

github : https://github.com/lucaong/jQCloud

Posted by lahuman
var win = window.open(url, wname, wfetures);

시 아래와 같은 오류가 발생할 경우, 

SCRIPT87 Message: Invalid argument. 


wname 에서 빈칸( )이나, 언더바(_) 가 들어가서 발생하는 오류일 가능성이 높다.


Microsoft 에서는 두번째 인자를 아래와 같이 사용하라고 권고 한다.

http://msdn.microsoft.com/en-us/library/ms536651%28v=vs.85%29.aspx


wname 인자에는  target의 속성을 입력하라 되어 있다.

  • _blank
  • _media
  • _parent
  • _search
  • _self
  • _top


IE 에서만 발생하여 대략 난감할 수 있음



참조 : http://stackoverflow.com/questions/710756/ie8-var-w-window-open-message-invalid-argument

Posted by lahuman