2011-06-21 51 views
1

的單擊事件我動態添加一個選擇按鈕,可以單擊以從列表中選擇一個給定的接觸被附加到表。動態添加按鈕(使用jQuery)必須被點擊了兩次火已經被綁定到按鈕

我要在文檔中的任意位置單擊之前,我可以點擊動態添加按鈕。顯然,動態按鈕的綁定事件在第一次單擊之後纔會綁定。

順便說一句,在當前版本的函數中,我將一個點擊事件綁定到每個動態按鈕的文檔正文,然後查看事件目標是否是相關的動態按鈕,此時我會觸發所需的功能傳回選定的聯繫人。我轉而採用這種方法,給予他人經歷我在這裏描述的同樣事情的建議。在實現之前,我有一個非常傳統的$ J(「#btnId」)。bind('click',{....},function(event){...});方法來綁定點擊事件,這導致了在點擊事件觸發動態按鈕之前必須點擊兩次的相同體驗。我也從其他角度出發,使用jQuery的.bind,.live,.delegate方法,在所有情況下,我必須點擊兩次,才能實際觸發按鈕的點擊事件。

function PickContacts() { 
    if ($J("#tblCp").length > 0) { 
     var broad = $J("#chkCpBroad").prop("checked"); 
     var contactType = GetCheckBoxListValues("divCpContactType"); 
     var contactId = ""; 
     if ($J("#txtCpContactId").length > 0) { 
      contactId = $J("#txtCpContactId").val(); 
     } 
     var contactName = $J("#txtCpContactName").val(); 
     var firstName = $J("#txtCpFirstName").val(); 
     var lastName = $J("#txtCpLastName").val(); 
     var email = $J("#txtCpEmail").val(); 
     var allMatches = $J("#chkCpAllMatches").prop("checked"); 
     var rows = ParseInts($J("#txtCpRowsReturned").val(), 10); 
     if (rows === 0) { 
      rows = 15; 
     } 
     var crmSeatsOnly = false; 
     if (cpCrmSeatsOnly !== null && cpCrmSeatsOnly === "Y") { 
      crmSeatsOnly = true; 
     } 
     var tbl = $J("#tblCpResults"); 
     tbl.empty(); 
     if (contactId !== "" || contactName !== "" || firstName !== "" || lastName !== "" || email !== "") { 
      $J.ajax({ 
       type: "POST", 
       url: "/ClientBin/Contact.asmx/ContactPicker", 
       data: "{'broad':" + broad + ",'contactType':'" + contactType + "','contactId':'" + contactId + "','contactName':'" + contactName + "','firstName':'" + firstName + "','lastName':'" + lastName + "','email':'" + email + "','allMatches':" + allMatches + ",'crmSeatsOnly':" + crmSeatsOnly + ",'rows':" + rows + "}", 
       contentType: "application/json; charset=utf-8", 
       context: tbl, 
       success: function (result) { 
        if (result.d !== "TIME OUT") { 
         var JObject = ParseJson(result.d); 
         if (JObject !== null) { 
          if (JObject.RESULT[0].SUCCESS) { 
           var alternatingRow = false; 
           var c = JObject.CONTACT; 
           for (i = 0; i < c.length; i++) { 
            var trStyle = "rowstyleNoBorder"; 
            if (alternatingRow) { 
             trStyle = "alternatingrowstyleNoBorder"; 
             alternatingRow = false; 
            } 
            else { 
             alternatingRow = true; 
            } 

            this.append('<tr class="' + trStyle + '"><td><span id="lblCpContactId' + i + '">' + c[i].CONTACT_ID + '</span></td><td><span id="lblCpContactName' + i + '">' + c[i].CONTACT_NAME + '</span></td><td><span id="lblCpFirstName' + i + '">' + c[i].FIRST_NAME + '</span></td><td><span id="lblCpLastName' + i + '">' + c[i].LAST_NAME + '</span></td><td valign="top"><input type="submit" id="btnCpSelect' + i + '" value="' + $J("#hdnCpTransSelect").val() + '" title="' + $J("#hdnCpTransSelectContact").val() + '" /></td></tr>'); 

            $J("body").bind('click', { index: i, contactId: c[i].CONTACT_ID, contactName: c[i].CONTACT_NAME, firstName: c[i].FIRST_NAME, lastName: c[i].LAST_NAME }, function (event) { 
             if ($J(event.target).is("#btnCpSelect" + event.data.index)) { 
              SelectContact(event.data.contactId, event.data.contactName, event.data.firstName, event.data.lastName); 
              return false; 
             } 
            }); 
            // Copy button css styling from an existing on page button by passing the IDs for both buttons to the CopyBtnStyle fn. 
            CopyBtnStyle("btnCpSelect" + i, "btnCpClose"); 
           } 
          } 
          else { 
           this.append('<tr><td><span id="lblCpNoRows">' + JObject.RESULT[0].FEEDBACK + '</span></td></tr>'); 
          } 
         } 
        } 
        else { 
         TimeOut(); 
        } 
       }, 
       error: function (XMLHttpRequest, textStatus, errorThrown) { 
        WsFail(XMLHttpRequest, textStatus, errorThrown); 
       } 
      }); 
     } 
    } 
} 
+0

牆上的文字警示!一個簡短的,簡潔的例子,用最少量的不相關的代碼加上點對點的問題通常會產生更快更好的答案。 – DarthJDG

+0

Tks的建議DarthJDG ...我從來沒有張貼在堆棧流量,可能已經做了瓦特/我的第一個職位的問題。我縮短了相應的希望獲得更多的閱讀。 – marsh76

+0

修正你的帖子+1,歡迎來到SO!這樣的綁定事件並不是很好的做法,你應該使用'。委託()',它做了一個非常類似的事情,利用事件冒泡和檢查原始選擇器對'event.target'。你也不應該爲每一行綁定一個單獨的事件,特別是如果你有分頁,你最終可能會有數百個未使用但綁定的事件觸發每次點擊。必須有其他事情發生,你確定你沒有任何事件有條件地在DOM樹上調用'event.stopPropagation()'? – DarthJDG

回答

2

好吧......我到底層的東西在這裏。我不知道爲什麼在技術上這是一個問題,也許更有知識的貢獻者在這裏可以解釋這對我的一個,但我具有點擊兩次這些動態按鈕觸發點擊事件問題的事實,引起我已經連接了我的「PickContacts」JS函數,以便在窗體中的按鍵和模糊事件中對文本輸入字段進行調用。雖然顯然有點多餘,但我只是不確定爲什麼這會是一個問題,因爲在我調用WS方法來檢索聯繫人列表之前,我會清空WS方法發回的結果所在的表顯示。所以,我會假設,隨着表格行和它們的元素被從DOM中移除,那麼在鍵上或模糊處(先出現者)已經綁定到動態按鈕的單擊事件也會如此。

我可以肯定地說的是我可以觀察到的,也就是說,在我從文本輸入字段中刪除其中一個事件之後,將其他任何一個都移除了,我必須點擊兩次之前的問題獲取按鈕的點擊事件觸發已解決。

如果還有人在那裏,知道爲什麼技術通過結合這兩個事件中調用該函數建立名單將創建問題,我很想以更好地瞭解它的基本水平。

在任何情況下,我再次感謝雙方PetersonDidIt和DarthJDG給予的注意。

1

有很多事情可以做,使這項工作更好。我修改了一些代碼,並添加了很多的意見,試圖解釋爲什麼我所做的更改:http://jsbin.com/ipuki5/2/edit

或質量代碼塊:

// Create an easy to edit template for our row 
var contactsRowtmpl = '<tr class="%trStyle%"><td><span id="lblCpContactId%index%">%CONTACT_ID%</span></td>'+ 
    '<td><span id="lblCpContactName%index%">%CONTACT_NAME%</span></td>'+ 
    '<td><span id="lblCpFirstName%index%">%FIRST_NAME%</span></td>'+ 
    '<td><span id="lblCpLastName%index%">%LAST_NAME%</span></td>'+ 
    '<td valign="top"><input type="submit" id="btnCpSelect%index%" class="CpSelect" value="%value%" title="%title%" /></td></tr>'; 

// Very simple templating function 
function template(tmpl, data) { 
    return tmpl.replace(/%(\w*)%/g,function(){ return data[ arguments[1] ] || "";}); 
} 

// Cache the table selector 
var tblCpResults = $J("#tblCpResults"); 
// Use delegate to bind the click event to for all input.CpSelet 
tblCpResults.delegate("click", ".CpSelect", function (event) { 
    // prevent the default action of the click event 
    event.preventDefault(); 
    // retrive the data from the row 
    var data = $(this).closest("tr").data("contact"); 
    // Select the contact 
    SelectContact(data.contactId, data.contactName, data.firstName, data.lastName); 
}); 

function PickContacts() { 
    if ($J("#tblCp").length > 0) { 
     var broad = $J("#chkCpBroad").prop("checked"); 
     var contactType = GetCheckBoxListValues("divCpContactType"); 
     var contactId = ""; 
     if ($J("#txtCpContactId").length > 0) { 
      contactId = $J("#txtCpContactId").val(); 
     } 
     var contactName = $J("#txtCpContactName").val(); 
     var firstName = $J("#txtCpFirstName").val(); 
     var lastName = $J("#txtCpLastName").val(); 
     var email = $J("#txtCpEmail").val(); 
     var allMatches = $J("#chkCpAllMatches").prop("checked"); 
     var rows = ParseInts($J("#txtCpRowsReturned").val(), 10); 
     if (rows === 0) { 
      rows = 15; 
     } 
     var crmSeatsOnly = false; 
     if (cpCrmSeatsOnly !== null && cpCrmSeatsOnly === "Y") { 
      crmSeatsOnly = true; 
     } 

     tblCpResults.empty(); 
     if (contactId !== "" || contactName !== "" || firstName !== "" || lastName !== "" || email !== "") { 
      $J.ajax({ 
       type: "POST", 
       url: "/ClientBin/Contact.asmx/ContactPicker", 
       // Use a normal object here much easier to maintain 
       data: { 
        'broad': broad, 
        'contactType': contactType, 
        'contactId': contactId, 
        'contactName': contactName, 
        'firstName': firstName, 
        'lastName': lastName, 
        'email': email, 
        'allMatches': allMatches, 
        'crmSeatsOnly': crmSeatsOnly, 
        'rows': rows 
       }, 
       contentType: "application/json; charset=utf-8", 
       success: function (result) { 
        if (result.d === "TIME OUT") { 
         TimeOut(); 
         return; 
        } 
        var JObject = ParseJson(result.d), 
         // Cache these selectors so we don't have to reselect them in the for loop 
         hdnCpTransSelect = $J("#hdnCpTransSelect"), 
         hdnCpTransSelectContact = $J("#hdnCpTransSelectContact"); 
        if (JObject !== null) { 
         if (!JObject.RESULT[0].SUCCESS) { 
          tblCpResults.append('<tr><td><span id="lblCpNoRows">' + JObject.RESULT[0].FEEDBACK + '</span></td></tr>'); 
          return; 
         } 
         var c = JObject.CONTACT; 
         // Create an empty jQuery object to stuff all of the rows in 
         var rows = $(); 
         for (i = 0; i < c.length; i++) { 
          c[ i ].trStyle = (i % 2) ? "alternatingrowstyleNoBorder" : "rowstyleNoBorder"; 
          c[ i ].index = i; 
          c[ i ].value = hdnCpTransSelect.val(); 
          c[ i ].title = hdnCpTransSelectContact.val(); 

          // Use the template function to handle creating our row 
          var row = template(contactsRowtmpl, c[ i ]); 
          // Add the contacts data to the row so we can retrive it later 
          $.data(row, "contact", c[ i ]); 
          // add the row to the rows jQuery object 
          rows = rows.add(row); 
          // Why do you need to copy the btn style? seems like this could be improved on. 
          CopyBtnStyle("btnCpSelect" + i, "btnCpClose"); 
         } 
         // Now that we are done looping add all the rows to the dom. 
         tblCpResults.append(rows); 
        } 
       }, 
       error: function (XMLHttpRequest, textStatus, errorThrown) { 
        WsFail(XMLHttpRequest, textStatus, errorThrown); 
       } 
      }); 
     } 
    } 
} 
+0

我會先說壞消息。我仍然需要單擊文檔中的任意位置,然後在點擊事件觸發前點擊按鈕。所以,我的核心問題依然存在。但是,我給你一些重要的道具來清理我的日常工作。而且,我喜歡這個模板概念。在我正在幫助開發的門戶網站中,我構建了許多動態UL,表格行,中繼器div等等。而且,在許多情況下,相同的模板可以提供多個動態列表。所以,非常感謝在這裏教給我一兩件事。我現在要調查DarthJDG的其他技巧WRT我需要點擊兩次觸發點擊事件。 – marsh76