无法读取null的属性`attachEvent`

时间:2014-09-24 17:20:07

标签: javascript

我有一个使用speechSynthesis的JavaScript文件。 我一直有这个错误:

"Cannot read property 'attachEvent' of null" in line 129:

这是:

speech.bind = function(event, element, callback) {
  **if (element.attachEvent) {**
    element.attachEvent('on'+event, callback )
  } else if (window.addEventListener) {
    element.addEventListener(event, callback ,false);
  };
};

我会在这里放置角色代码,这样任何人都可以检查整个JavaScript:

var speech_def = speech_def || {
   container: "#glb-materia"
  ,insert_before: true
  ,ico: "http://edg-1-1242075393.us-east-1.elb.amazonaws.com/speech/listen_icon.jpg"
  ,bt_txt: "OUÇA A REPORTAGEM"
  ,bt_stop: "PARAR!"
  ,source: ".materia-conteudo"
  ,ignore: [
     ".foto-legenda"
    ,".frase-materia"
    ,"script"
    ,"style"
    ,"#speech"
    ,".sub-header"
    ,".chamada-materia"
    ,".data-autor"
    ,".box-tags"
    ,".saibamais"
  ]
};

var speech = speech || {};

//Polyfill remove()
Element.prototype.remove = function() {
  this.parentElement.removeChild(this);
};
NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
  for (var i = 0, len = this.length; i < len; i++) {
    if(this[i] && this[i].parentElement) {
      this[i].parentElement.removeChild(this[i]);
    }
  }
};
//Polyfill innerText
if ( (!('innerText' in document.createElement('a'))) && ('getSelection' in window) ) {
  HTMLElement.prototype.__defineGetter__("innerText", function() {
    var selection = window.getSelection(),
        ranges    = [],
        str;
    for (var i = 0; i < selection.rangeCount; i++) {
      ranges[i] = selection.getRangeAt(i);
    }
    selection.removeAllRanges();
    selection.selectAllChildren(this);
    str = selection.toString();
    selection.removeAllRanges();
    for (var i = 0; i < ranges.length; i++) {
      selection.addRange(ranges[i]);
    }
    return str;
  })
}

speech.iOS = /(iPad|iPhone|iPod)/g.test( navigator.userAgent );
speech.Android = /(Android)/g.test( navigator.userAgent );

speech.include = function() {
  var bt = ""
  bt += '<div id="speech" '
          +'title="'+speech_def.bt_txt+'" '
          +'style="'
            +'display: none; '
            +'margin: 5px; '
            +'font-size: 12px; '
            +'font-style: italic; '
            +'color: #bbbbbb; '
            +'cursor: pointer;"'
          +'>';
    bt += '<img style="width: 25px; height: 25px;" src="'+speech_def.ico+'"> ';
    bt += '<i style="vertical-align: top; line-height: 28px;">'+speech_def.bt_txt+'</i>';
  bt += '</div>';
  var button = document.createElement("SPAN");
  button.innerHTML = bt;
  var box = document.querySelectorAll(speech_def.container)[0];
  if (speech_def.insert_before) {
    box.insertBefore(button,box.firstChild);
  } else {
    box.appendChild(button) 
  };
};

speech.stop = function() {
  window.speechSynthesis.cancel();
}
speech.stop();

speech.content = function() {
  var result = "";
  var boxes = speech_def.source.split(",");
  boxes.reverse();
  for (var n = boxes.length - 1; n >= 0; n--) {
    var doc = document.querySelector(boxes[n]);
    if (doc) {
      doc = doc.cloneNode(true);
      for (var i = speech_def.ignore.length - 1; i >= 0; i--) {
        var els = doc.querySelectorAll(speech_def.ignore[i]);
        for (var j = els.length - 1; j >= 0; j--) {
          els[j].remove();
        };
      };
      result += "." + doc.innerText;
    };
  };
  return result;
};

speech.start_speech = function() {
  var content = speech.content();
  // Note: some voices don't support altering params
  if (!speech.Android) speech.msg.voice = speech.voices[0];
  // msg.voiceURI = 'native';
  speech.msg.volume = speech.iOS?1:1; // 0 to 1
  speech.msg.rate = speech.iOS?0.6:1; // 0.1 to 10
  speech.msg.pitch = speech.iOS?1:1; // 0 to 2
  speech.msg.text = content;
  speech.msg.lang = 'pt-BR';

  speech.msg.onend = function(e) {
    // console.log('Finished in ' + event.elapsedTime + ' seconds.');
  };

  window.speechSynthesis.speak(speech.msg);
};
speech.read = function(){}; //chrome problem

speech.bind = function(event, element, callback) {
  if (element.attachEvent) {
    element.attachEvent('on'+event, callback )
  } else if (window.addEventListener) {
    element.addEventListener(event, callback ,false);
  };
};

speech.click = function(e){
  event.stopPropagation()
  if (window.event) window.event.cancelBubble = true;
  var control = document.getElementById("speech");
  var label;
  if (window.speechSynthesis.speaking) {
    label = speech_def.bt_txt;
    speech.stop();
  } else {
    label = speech_def.bt_stop;
    speech.start_speech();
  };
  control.querySelector("i").innerHTML = label;
}

speech.bind_button = function() {
  var control = document.getElementById("speech");
  speech.bind("click",control,speech.click);
}; 

speech.show_button = function() {
  if (!speech.on_page) {
    speech.on_page = true;
    speech.include();
    speech.bind_button();
  };
  var control = document.getElementById("speech");
  control.style.display="inline-block";
};

speech.test_portuguese = function() {
  speech.voices = [];
  window.speechSynthesis.getVoices().forEach(function(voice) {
    if (voice.lang == "pt-BR") {
      speech.voices.push(voice);
    };
  });
  if (speech.Android) {
    var control = document.getElementById("speech");
    var complement = (speech.voices.length > 0)?"*":"";
    // control.querySelector("i").innerHTML = "OUÇA A REPORTAGEM"+complement;
    return true;
  } else {
    return (speech.voices.length > 0);
  };
};

speech.start = function() {
  if ('speechSynthesis' in window) {
    speech.msg = new SpeechSynthesisUtterance();
    if (speech.test_portuguese()) {
      speech.show_button();
    } else {
      window.speechSynthesis.onvoiceschanged = function() {
        if (speech.test_portuguese()) {
          speech.show_button();
        };
      };
    };
    speech.bind_button();
  };
};

speech.start();
speech.bind("load",window,speech.start)

我该如何解决这个问题? 非常感谢。

1 个答案:

答案 0 :(得分:0)

问题是此时element为空。

可能是因为没有id="speech"的元素,因此此代码中的control中只有null

speech.bind_button = function() {
  var control = document.getElementById("speech");
  speech.bind("click",control,speech.click);
};