docs: function(elem, callback, errback, timeout) {
          var timeoutHandler = null;
          var that = this;
  
          if (typeof(elem.tree) === "function") {
              elem = elem.tree();
          }
          var id = elem.getAttribute('id');
  
          // inject id if not found
          if (!id) {
              id = this.getUniqueId("sendIQ");
              elem.setAttribute("id", id);
          }
  
          var expectedFrom = elem.getAttribute("to");
          var fulljid = this.jid;
  
          var handler = this.addHandler(function (stanza) {
              // remove timeout handler if there is one
              if (timeoutHandler) {
                  that.deleteTimedHandler(timeoutHandler);
              }
  
              var acceptable = false;
              var from = stanza.getAttribute("from");
              if (from === expectedFrom ||
                 (expectedFrom === null &&
                     (from === Strophe.getBareJidFromJid(fulljid) ||
                      from === Strophe.getDomainFromJid(fulljid) ||
                      from === fulljid))) {
                  acceptable = true;
              }
  
              if (!acceptable) {
                  throw {
                      name: "StropheError",
                      message: "Got answer to IQ from wrong jid:" + from +
                               "\nExpected jid: " + expectedFrom
                  };
              }
  
              var iqtype = stanza.getAttribute('type');
              if (iqtype == 'result') {
                  if (callback) {
                      callback(stanza);
                  }
              } else if (iqtype == 'error') {
                  if (errback) {
                      errback(stanza);
                  }
              } else {
                  throw {
                      name: "StropheError",
                      message: "Got bad IQ type of " + iqtype
                  };
              }
          }, null, 'iq', ['error', 'result'], id);
  
          // if timeout specified, setup timeout handler.
          if (timeout) {
              timeoutHandler = this.addTimedHandler(timeout, function () {
                  // get rid of normal handler
                  that.deleteHandler(handler);
                  // call errback on timeout with null stanza
                  if (errback) {
                      errback(null);
                  }
                  return false;
              });
          }
          this.send(elem);
          return id;
      }