如何克隆元素及其相关的事件回调?

时间:2015-10-26 17:54:02

标签: javascript jquery dom clone

我正在克隆一个元素并将其添加到DOM中。我预计新创建的克隆元素中的this将引用自身,但它似乎引用了原始克隆元素。

为了说明,我创建了以下脚本。通过单击&#34; cloneIt&#34;,添加一个新元素,并在单击新元素时,data('type')引用原始克隆。我的愿望是$('.fileupload').fileupload({ start: function (e, data) { console.log('start', this, $(this).parent().data('type')); } }) .on('fileuploadsubmit', function (e, data) { console.log('fileuploadsubmit', this, $(this).parent().data('type')); }); $('#cloneIt').click(function () { $('#clone').clone(true).removeAttr('id').data('type', 'added').appendTo('#container'); }); #clone { display:none; } <button id="cloneIt">cloneIt</button> <ul id="container"> <li id="clone" data-type="clone"> <input class="fileupload" name="file" type="file" /> </li> <li data-type="existing"> <input class="fileupload" name="file" type="file" /> </li> </ul> 显示&#34;添加&#34;。

如何克隆元素并使回调属于新克隆的对象?

https://stackoverflow.com/

#include <stdio.h>
#include <stdlib.h>  // rand(), srand()
#include <time.h>    // time()

// Size of the board (square)
const int  BOARD_SIZE     = 3;

// Symbols used for the board
const char BLANK_SYMBOL   = ' ';
const char COMP_SYMBOL    = 'O';
const char HUMAN_SYMBOL   = 'X';

// Human goes first
const int  HUMANS_TURN    = 0;
const int  COMPUTERS_TURN = 1;


// Function prototypes
void initializeBoard(char board[BOARD_SIZE][BOARD_SIZE]);
int  hasWon(char board[BOARD_SIZE][BOARD_SIZE], char mark);
int  hasWonHorizontal(char board[BOARD_SIZE][BOARD_SIZE], char mark);
int  hasWonVertical(char board[BOARD_SIZE][BOARD_SIZE], char mark);
int  hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark);
void getComputerMove(char board[BOARD_SIZE][BOARD_SIZE]);
void getHumanMove(char board[BOARD_SIZE][BOARD_SIZE]);
void printBoard(char board[BOARD_SIZE][BOARD_SIZE]);
void clearScreen(void);


//
// The main function should not be changed
//
int main(void) {
   char board[BOARD_SIZE][BOARD_SIZE];
   int  humanWon    = 0; // boolean (0/1)
   int  computerWon = 0; // boolean (0/1)
   int  move        = 0;

   // Seed the random number generator
   srand(time(0));

   initializeBoard(board);

   while ((move < (BOARD_SIZE * BOARD_SIZE)) && !humanWon && !computerWon) {
      clearScreen();

      if ((move % 2) == COMPUTERS_TURN) {
         getComputerMove(board);
      } else {
         printBoard(board);
         getHumanMove(board);
      }

      computerWon = hasWon(board, COMP_SYMBOL);
      humanWon    = hasWon(board, HUMAN_SYMBOL);
      move++;
   }

   clearScreen();
   printBoard(board);

   if (humanWon) {
      printf(">>>> You won!\n");
   } else if (computerWon) {
      printf("<<<< I won!\n");
   } else { // move >= BOARD_SIZE * BOARD_SIZE
      printf("==== A Draw\n");  
   }

   return 0;
}


//
// Initialized the board to all BLANK_SYMBOL
//
void initializeBoard(char board[BOARD_SIZE][BOARD_SIZE]) {
   int row;

   for (row = 0; row < BOARD_SIZE; row++) {
      int col;

      for (col = 0; col < BOARD_SIZE; col++) {
         board[row][col] = BLANK_SYMBOL;
      }
   }
}


//
// Determines if the 'mark' completely fills a row, column, or diagonal
// returns 1 if yes, 0 if no
//
int hasWon(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
   return    hasWonHorizontal(board, mark)
      || hasWonVertical(board, mark)
      || hasWonDiagonal(board, mark);
}


//
// Determines if the 'mark' completely fills a row
// returns 1 if yes, 0 if no
//
int hasWonHorizontal(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
   int won = 0; // boolean (0/1).  Assume lost until proven true
   int row;

   for (row = 0; row < BOARD_SIZE && !won; row++) {
      int match = 1; // boolean (0/1)
      int col;

      for (col = 0; col < BOARD_SIZE; col++) {
         if (board[row][col] != mark) {
            match = 0;
         }
      } 

      won = match;
   }

   return won;
}


//
// Determines if the 'mark' completely fills a column
// returns 1 if yes, 0 if no
//
int hasWonVertical(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
   int won = 0;
   int col;

   for (col = 0; col < BOARD_SIZE && !won; col++) {
      int match = 1;
      int row;

      for (row = 0; row< BOARD_SIZE; row++) {
         if(board[row][col] != mark) {
            match = 0;
         }
      }

      won = match;
   }

   return won; // Stub -- make this return the correct value
}


//
// Determines if the 'mark' completely fills a diagonal
// returns 1 if yes, 0 if no
//
int hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
   int won = 0;
   int match = 1;
   int col;

   for (col = 0; col < BOARD_SIZE && !won; col++) {
      if(board[col][col] != mark) {
         match=0;
      }
      else if(board[BOARD_SIZE-col-1][col] != mark){
         match=0;
      } 
   } 
   won = match;

   return won; // Stub -- make this return the correct value
}


//
// Gets computer move by randomly picking an unoccupied cell
//
void getComputerMove(char board[BOARD_SIZE][BOARD_SIZE]) {
   int row;
   int col;

   do {
      row = rand() % BOARD_SIZE;
      col = rand() % BOARD_SIZE;
   } while (board[row][col] != BLANK_SYMBOL);

   board[row][col] = COMP_SYMBOL;
}


//
// Gets human move by prompting user for row and column numbers
//
void getHumanMove(char board[BOARD_SIZE][BOARD_SIZE]) {
   int rowu;
   int colu;
   printf("Select the value of the row for your move: ");
   scanf("%i", &rowu);
   printf("Select the value of the column for you move: ");
   scanf("%i", &colu);

   board[rowu][colu] = HUMAN_SYMBOL;
}


//
// Prints the board to the screen.  Example:
//
//       0   1   2
//     +---+---+---+
//   0 | X |   |   |
//     +---+---+---+
//   1 |   | O | O |
//     +---+---+---+
//   2 |   |   | X |
//     +---+---+---+
//
void printBoard(char board[BOARD_SIZE][BOARD_SIZE]) {
   printf("   0   1   2\n");
   printf(" +---+---+---+\n");
   printf("0| %c | %c | %c |\n",board[0][0],board[0][1],board[0][2]);
   printf(" +---+---+---+\n");
   printf("1| %c | %c | %c |\n",board[1][0],board[1][1],board[1][2]);
   printf(" +---+---+---+\n");
   printf("2| %c | %c | %c |\n",board[2][0],board[2][1],board[2][2]);
   printf(" +---+---+---+\n");
}



//
// Clears the screen -- uses ANSI terminal control codes
//
void clearScreen(void) {
   const char ESC = 27;

   printf("%c[2J%c[H", ESC, ESC);
}

2 个答案:

答案 0 :(得分:2)

.fileupload()被调用时,this的启动回调概念会被锁定,而.fileupload()会被转移到克隆。

就个人而言,我会将模板LI与实时LI分开,并且永远不会在其上调用<button id="cloneIt">cloneIt</button> <ul id="template"> <li data-type="original"> <input class="fileupload" name="file" type="file" /> </li> </ul> <ul id="container"> <li data-type="existing"> <input class="fileupload" name="file" type="file" /> </li> </ul>

<强> HTML

#template {
    display:none;
}

<强> CSS

.fileupload()

最初,仅在#container中的INPUT上调用$('#container .fileupload').fileupload({ start: function (e, data) { console.log('start', this, $(this).parent().data('type')); } }).on('fileuploadsubmit', function (e, data) { console.log('fileuploadsubmit', this, $(this).parent().data('type')); }); $('#cloneIt').click(function () { $('#template li').clone().data('type', 'clone').appendTo('#container').find('.fileupload').fileupload(...); }); ,然后在模板生成之后调用该模板的任何克隆。

<强>的Javascript

-5 3 -0.6
-4 3 -0.75
-3 3 -1
-2 3 -1.5
-1 3 -3
0 3 -33   //Expected
1 3 -33   //I want it to continue evaluating the expression, not default 
2 3 -33
3 3 -33
4 3 -33

我建议使用任何插件来实现此方法。克隆一个widgetized元素是危险的。克隆行为不能保证可靠。有了一些插件,你可以侥幸逃脱;与其他人一起,你赢了。

答案 1 :(得分:1)

http://jsfiddle.net/1as47aeb/5/

在创建DOM对象之后,似乎需要再次从库中调用fileupload方法。

如果您检查代码中的DOM,您会看到该属性已存在,已添加,您可以在克隆后在原始代码中查询该属性。

编辑

更正了在克隆输入中上传时调用的两个输入事件的行为。