1. 程式人生 > >Snap Build Your Own Blocks輸入中文解決辦法

Snap Build Your Own Blocks輸入中文解決辦法

val 它的 解決方法 關心 信息 span 技術分享 應該 輸出

Snap Build Your Own Blocks輸入中文解決辦法

Snap! (formerly BYOB) is a visual, drag-and-drop programming language. It is an extended reimplementation of Scratch (a project of the Lifelong Kindergarten Group at the MIT Media Lab) that allows you to Build Your Own Blocks. It also features first class[1] lists, first class procedures, and continuations[2]. These added capabilities make it suitable for a serious introduction to computer science for high school or college students.

快照!(以前 BYOB) 是一種可視的拖放編程語言。這是一個擴展的重新實施(一個項目的終身幼兒園小組在麻省理工學院媒體實驗室), 讓你建立自己的塊。它還具有第一類 [1] 列表、第一類過程和延續 [2]。這些新增功能使其適合於對高中或大學生進行計算機科學的認真介紹。

它加州伯克利大學編寫的一套開源圖形化編程,它的官網在:https://snap.berkeley.edu;在頁面有更為詳細的介紹,並且在編程界面的左上角(如圖 1)的圖表點擊一下即可以下載該圖形化編程的源代碼。

技術分享圖片

圖 1

到目前在編程界面中除了能夠輸入英文之外,其他語言均不能正常輸入,曾經在GIT上面找到了一個解決中文輸入的方案,根據它的修改之後,確實能夠進行中文輸入,但是,輸入體驗,不是很好,簡單說就是輸入過程不能夠像在頁面的輸入框中輸入那樣流暢。有時候光標還會亂跳,這個方案的訪問地址,忘了,後期沒有找到。

我的解決方法也是在那個基礎上進行改良的,但是方式不一樣。

現在我們先確定一下,為了實現中文的輸入,我們應該修改哪一個源文件:morphic.js;這個源文件存放了圖形化編程界面的核心:主要包含了,所有的類的基類Morph,然後是一堆繼承者:CursorMorph(Snap 自定義的光標)MouseSensorMorph(自定義的鼠標事件)、DialMorph(彈窗)、HandleMorph(事件,轉發)、StringMorph等等。

在這裏我們只關心CursorMorph這一個類。然後再關註他的幾個方法:

  • CursorMorph.prototype.init 這個是CursorMorph的初始化
  • CursorMorph.prototype.initializeClipboardHandler 看源碼可分析出這個完成創建一個textarea,可編輯域
  • this.clipboardHandler.addEventListener( ‘keydown‘, …) 為可編輯域添加事件keydown
  • this.clipboardHandler.addEventListener(input, …) 為可編輯域添加事件input
  • CursorMorph.prototype.processKeyPress 響應keypress事件
  • CursorMorph.prototype.processKeyDown 響應keydown事件
  • CursorMorph.prototype.insert(aChar, shiftKey) 在編輯域中添加字符,第二個參數是個bool值,判定當前shift鍵是否按下過。

下面,再給出我自己修改的思路:我們先想想一下,自己進行全拼音中文輸入時,在最後選定要輸入的中文,都會按下一個 空格或者阿拉伯數字1至9,來選定漢字;這也就代表了一次中文輸入結束。便出現問題1:根據什麽東西來判定當前一次中文輸入結束了呢?問題2:用戶選定的要輸入的中文字符內容存放在哪裏的?

解決第一個問題:需要分析源代碼:

this.clipboardHandler.addEventListener(

‘keydown‘,

function (event) {…},

false);

中回調函數function(event)中參數event存放了哪些內容,通過瀏覽器頁面調試打印,我們可以查看到如下信息:

技術分享圖片

圖 2 Opera瀏覽器中打印出的信息

技術分享圖片

圖 3搜過瀏覽器中的輸出

我們可以發現:兩個瀏覽器輸出的內容並不相同,Opera有一個key成員,少一個keyIdentifier;而搜狗瀏覽器與之相反;但兩者又一個共有的成員which,並且值都為229。通過測試谷歌瀏覽器也同樣有這個值。

然後通過空格或數字1到9選定漢字時,打印的信息是:

技術分享圖片

技術分享圖片

因子,我們可以在利用code成員的值,來判斷一次中文輸入是否結束;

這樣,第一個問題也算是得到了解決。

下面,我們來解決第二個問題:用戶所選定輸入的中文字符存放在哪裏的,此時:

this.clipboardHandler.addEventListener(

‘input‘,

function (event) {},

false);

代碼中function(event)中參數event中存放的內容;

以及CursorMorph.prototype.initializeClipboardHandler=function(){…}代碼中的this.clipboardHandler這個成員,它是HTML對象textarea,獲取textarea的值的方法是:

var cval = this.clipboardHandler.value;學習過前端的都知道。

現在通過瀏覽器終端打印輸出信息,來看看內容:

技術分享圖片

圖 4 Opera瀏覽器的輸出

技術分享圖片

圖 5 搜狗瀏覽器的輸出

可以發現,Opera的event的成員含有data成員,而搜狗瀏覽器沒有該成員;但它們共育是this.clipboardHandler.value的值是相同的,並且在Opera瀏覽中,它的值與event.data的值相同。那麽這樣用戶輸入的中文的值,我們也就找到了;

最後一個問題:我們怎麽把這個字,插入到相應的文本框中呢。

是否還記得前面提及的CursorMorph.prototype.insert(aChar, shiftKey)這個成員函數;它便可以解決該問題。

下面給出修改後的源碼,並標記出修改的地方,源文件morphic.js:

CursorMorph.prototype.init = function (aStringOrTextMorph) {

var ls;

//這一行,是自己需要添加的,判定當前是否正在進行中文輸入

this.isInputCH = false ;

//這一行,是自己需要添加的,判定一次中文輸入是否結束

this.isInputChED = false ;

// additional properties:

this.keyDownEventUsed = false;

this.target = aStringOrTextMorph;

this.originalContents = this.target.text;

this.originalAlignment = this.target.alignment;

this.slot = this.target.text.length;

CursorMorph.uber.init.call(this);

ls = fontHeight(this.target.fontSize);

this.setExtent(new Point(Math.max(Math.floor(ls / 20), 1), ls));

this.drawNew();

this.image.getContext(‘2d‘).font = this.target.font();

if (this.target instanceof TextMorph &&

(this.target.alignment !== ‘left‘)) {

this.target.setAlignmentToLeft();

}

this.gotoSlot(this.slot);

this.initializeClipboardHandler();

};

CursorMorph.prototype.initializeClipboardHandler = function () {

// Add hidden text box for copying and pasting

var myself = this,

wrrld = this.target.world();

this.clipboardHandler = document.createElement(‘textarea‘);

this.clipboardHandler.style.position = ‘absolute‘;

this.clipboardHandler.style.top = window.outerHeight;

this.clipboardHandler.style.right = ‘101%‘; // placed just out of view

document.body.appendChild(this.clipboardHandler);

this.clipboardHandler.value = this.target.selection();

this.clipboardHandler.focus();

this.clipboardHandler.select();

this.clipboardHandler.addEventListener(

‘keypress‘,

function (event) {

myself.processKeyPress(event);

this.value = myself.target.selection();

this.select();

},

false

);

this.clipboardHandler.addEventListener(

‘keydown‘,

function (event) {

var kcode = event.code.substring(0,5);

console.log(event);

console.log("kcode="+kcode+";which="+event.which);

console.log("keyIdentifier="+event.keyIdentifier);

// if ( (event.key && event.key === ‘Process‘) ||

// (event.keyIdentifier && event.which === 229)){

if ( event.which === 229) { //所有瀏覽器共有的特征和值

// 在中文輸入過程時,空格為選中漢字

myself.isInputCH = true; //設為真表示正在進行中文輸入

//設為真表示一次中文輸入結束

myself.isInputChED = (kcode === ‘Space‘ || kcode === ‘Digit‘)?true:false;

console.log("判定當前正在進行中文輸入");

}

myself.processKeyDown(event);

if (event.shiftKey) {

wrrld.currentKey = 16;

}

this.value = myself.target.selection();

this.select();

// Make sure tab prevents default

if (event.key === ‘U+0009‘ ||

event.key === ‘Tab‘) {

myself.processKeyPress(event);

event.preventDefault();

}

},

false

);

this.clipboardHandler.addEventListener(

‘keyup‘,

function (event) { wrrld.currentKey = null;},

false

);

this.clipboardHandler.addEventListener(

‘input‘,

function (event) {

var ival = myself.clipboardHandler.value ;

console.log("============ input ==========");

console.log(event);

console.log(myself.target);

console.log("[cliph data="+ival+";event data="+event.data+"]");

console.log("[char="+ival+",len="+ival.length+",isch="+myself.isInputCH+",ised="+myself.isInputChED+"]");

//這個條件下,表示輸入的是 中文漢字

if ( myself.isInputCH && myself.isInputChED ){

console.log(">>>>QQ輸入法和搜狗輸入法");

//支持了QQ輸入法和搜狗輸入法

myself.insert(ival,event.shiftKey);

// myself.isInputChED = myself.isInputCH = event.data !== ‘ ‘?false:true ;

myself.isInputChED = myself.isInputCH = false ;

}else if ( (ival.length ===1 || ival.length === 2 ) &&

myself.isInputCH && ival !== ‘ ‘ &&

(ival < ‘a‘ || ival > ‘z‘) && (ival < ‘A‘ || ival > ‘Z‘)){

//表示輸入的是 中文的字符,如逗號,句號等等

console.log(">>>>other input software...");

myself.insert(ival,event.shiftKey);

myself.isInputCH = false ;

}

// if (this.value === ‘‘) {

// myself.gotoSlot(myself.target.selectionStartSlot());

// myself.target.deleteSelection();

// }

},

false

);

};

這種修改方案有一個小BUG是這樣的,當進行輸入中文時,一般情況下,鍵入完拼音後,在鍵入shift鍵,那麽輸入的便是之前 鍵入的拼音;但在這個解決辦法中,不能夠完成該操作。

Snap Build Your Own Blocks輸入中文解決辦法