javascript - trick/guideline to remove DOM element

清理DOM元素

remove an element is not as simple as calling parent.RemoveChild, housekeeping include 

 

  1. remove element should clean the handler that is associated with the element, otherwise, IE will leak memory should the function reference an external DOM element
  2. remove the data associated with the element
  3. remove should happen on the element (the parent) and all its descendant

and there is a caveat on IE, where most browsers will reclaim the memory happily, IE does not reclaim the memory that is occupied by the removed elements until the page is left.  


I am giving a pseudo-code as follow to show you you would normally write the remove function if  you ever need to do so. 


/**
* @Comment: this shows you how to remove DOM element from the tree, it worth the discussion because  
*   1. remove element should clean the handler that is associated with the element, otherwise, IE will leak memory should the function reference an external DOM element
*   2. remove the data associated with the element
*   3. remove should happen on the element (the parent) and all its descendant
* one caveat abou the remove, after the removal of the element, browsers may have different strategy to reclaim the memory it used, IE is an exception where it fail to reclaim 
* the memory until the page is finally left. 
* 
* so, for IE,an additional step is to set the outerHTML = "" (a trick) , which will wipe out elment from IE's memory more completely than simply doing removing child. 
*
* NOTE: this code shows example, and is not supposed to be useful without context.
*/
function remove() {
  // go through all descendants and the element to be removed.
  jQuery("*", this).add([this]).each(function () {
    // remove all bound events 
    jQuery.event.remove(this);
    // remove attached data
    jQuery.removeData(this);
  });
  // remove the element (if it 's in the DOM)
 
  if (this.parentNode) {
    this.parentNode.removeChild(this);

  // if it is IE, you will need to set the outerHTML as well
    if (typeof this.outerHTML !== "undefined")
      this.outerHTML = "";
  
  }
}
 
module TOP( input wire clk_50M , input wire rst_n , output wire ad_clk , input wire [7:0]ad_data , output wire [7:0]da_data , output wire da_clk ); wire lock ; wire clk_125M ; wire clk_35M ; wire clk_10M ; assign da_clk = clk_50M ; assign ad_clk = clk_50M ; ad_clock_125m u_pll ( .clkin1(clk_50M), // input .lock(lock), // output .clkout0(clk_125M) , // output .clkout1(clk_35M), // output .clkout2(clk_10M) // output // output ); wire wr_en_from_ad; wire [7:0] wr_data; ad_in u_ad( .ad_clk(ad_clk), .rst_n(rst_n), .ad_data(ad_data), .wr_en(wr_en_from_ad), .wr_data(wr_data) ); // // ---------- Parameters for address width ---------- // localparam ADDR_W = 10; // localparam PTR_W = ADDR_W + 1; // extra MSB for full/empty detection // localparam DEPTH = (1 << ADDR_W); // // ---------- write-side pointers (in ad_clk domain) ---------- // reg [PTR_W-1:0] wr_ptr_bin; // reg [PTR_W-1:0] wr_ptr_gray; // // synced read pointer sampled into write domain // reg [PTR_W-1:0] rd_ptr_gray_sync1_wr, rd_ptr_gray_sync2_wr; // // ---------- read-side pointers (in da_clk domain) ---------- // reg [PTR_W-1:0] rd_ptr_bin; // reg [PTR_W-1:0] rd_ptr_gray; // // synced write pointer sampled into read domain // reg [PTR_W-1:0] wr_ptr_gray_sync1_rd, wr_ptr_gray_sync2_rd; // // outputs from sync // wire full; // wire empty; // // ---------- utility functions ---------- // function [PTR_W-1:0] bin2gray; // input [PTR_W-1:0] b; // begin // bin2gray = (b >> 1) ^ b; // end // endfunction // // (optional) gray2bin for debug - not used in synthesizable empty/full logic // function [PTR_W-1:0] gray2bin; // input [PTR_W-1:0] g; // integer i; // reg [PTR_W-1:0] b; // begin // b = g; // for (i = PTR_W-2; i >= 0; i = i - 1) // b[i] = b[i] ^ b[i+1]; // gray2bin = b; // end // endfunction // // ---------- write-side logic (ad_clk domain) ---------- // wire wr_en_gated; // assign wr_en_gated = wr_en_from_ad & ~full; // // increment write pointer when write happens // always @(posedge ad_clk or negedge rst_n) begin // if (!rst_n) begin // wr_ptr_bin <= {PTR_W{1'b0}}; // wr_ptr_gray <= {PTR_W{1'b0}}; // rd_ptr_gray_sync1_wr <= {PTR_W{1'b0}}; // rd_ptr_gray_sync2_wr <= {PTR_W{1'b0}}; // end else begin // // sync read pointer into write domain (two-stage) // rd_ptr_gray_sync1_wr <= rd_ptr_gray; // rd_ptr_gray_sync2_wr <= rd_ptr_gray_sync1_wr; // if (wr_en_gated) begin // wr_ptr_bin <= wr_ptr_bin + 1'b1; // wr_ptr_gray <= bin2gray(wr_ptr_bin + 1'b1); // end // end // end // // ---------- read-side logic (da_clk domain) ---------- // wire rd_en_gated; // used to read from RAM and feed DAC // assign rd_en_gated = (~empty); // continuous read when data available (you can gate by DAC ready) // always @(posedge da_clk or negedge rst_n) begin // if (!rst_n) begin // rd_ptr_bin <= {PTR_W{1'b0}}; // rd_ptr_gray <= {PTR_W{1'b0}}; // wr_ptr_gray_sync1_rd <= {PTR_W{1'b0}}; // wr_ptr_gray_sync2_rd <= {PTR_W{1'b0}}; // end else begin // // sync write pointer into read domain (two-stage) // wr_ptr_gray_sync1_rd <= wr_ptr_gray; // wr_ptr_gray_sync2_rd <= wr_ptr_gray_sync1_rd; // if (rd_en_gated) begin // rd_ptr_bin <= rd_ptr_bin + 1'b1; // rd_ptr_gray <= bin2gray(rd_ptr_bin + 1'b1); // end // end // end // // ---------- full / empty detection ---------- // // full: when next write pointer equals read pointer with MSBs inverted (classic) // wire [PTR_W-1:0] wr_ptr_gray_next; // assign wr_ptr_gray_next = bin2gray(wr_ptr_bin + 1'b1); // // full compare uses synchronized read pointer inside write domain // assign full = (wr_ptr_gray_next == {~rd_ptr_gray_sync2_wr[PTR_W-1:PTR_W-2], rd_ptr_gray_sync2_wr[PTR_W-3:0]}); // // empty: read pointer equals synchronized write pointer inside read domain // assign empty = (rd_ptr_gray == wr_ptr_gray_sync2_rd); // // ---------- connect addresses to ram (lower ADDR_W bits) ---------- // wire [ADDR_W-1:0] wr_addr; // wire [ADDR_W-1:0] rd_addr; // assign wr_addr = wr_ptr_bin[ADDR_W-1:0]; // assign rd_addr = rd_ptr_bin[ADDR_W-1:0]; // // ---------- ram instance (your existing IP) ---------- // wire [7:0] rd_data; // wire wr_clk = ad_clk; // wire rd_clk = da_clk; // ---------------- parameters ---------------- localparam ADDR_W = 10; localparam PTR_W = ADDR_W + 1; // one extra MSB localparam DEPTH = (1 << ADDR_W); localparam integer SAFE_GUARD = 4; // read must be at least SAFE_GUARD behind write // ---------------- write-side pointers (ad_clk domain) ---------------- reg [PTR_W-1:0] wr_ptr_bin; reg [PTR_W-1:0] wr_ptr_gray; // synchronized read pointer sampled into write domain (two-stage) reg [PTR_W-1:0] rd_ptr_gray_sync1_wr, rd_ptr_gray_sync2_wr; // ---------------- read-side pointers (da_clk domain) ---------------- reg [PTR_W-1:0] rd_ptr_bin; reg [PTR_W-1:0] rd_ptr_gray; // synchronized write pointer sampled into read domain (two-stage) reg [PTR_W-1:0] wr_ptr_gray_sync1_rd, wr_ptr_gray_sync2_rd; // after sync, convert gray->bin in read domain reg [PTR_W-1:0] wr_ptr_bin_sync_rd; // full / empty signals (derived) wire full; wire empty; // ---------------- functions ---------------- function [PTR_W-1:0] bin2gray; input [PTR_W-1:0] b; begin bin2gray = (b >> 1) ^ b; end endfunction function [PTR_W-1:0] gray2bin_f; input [PTR_W-1:0] g; integer i; reg [PTR_W-1:0] b; begin // MSB passes through b[PTR_W-1] = g[PTR_W-1]; for (i = PTR_W-2; i >= 0; i = i - 1) b[i] = b[i+1] ^ g[i]; gray2bin_f = b; end endfunction // ---------------- write-side logic (ad_clk domain) ---------------- wire wr_en_gated; assign wr_en_gated = wr_en_from_ad & ~full; always @(posedge ad_clk or negedge rst_n) begin if (!rst_n) begin wr_ptr_bin <= {PTR_W{1'b0}}; wr_ptr_gray <= {PTR_W{1'b0}}; rd_ptr_gray_sync1_wr <= {PTR_W{1'b0}}; rd_ptr_gray_sync2_wr <= {PTR_W{1'b0}}; end else begin // sync read pointer into write domain rd_ptr_gray_sync1_wr <= rd_ptr_gray; rd_ptr_gray_sync2_wr <= rd_ptr_gray_sync1_wr; if (wr_en_gated) begin wr_ptr_bin <= wr_ptr_bin + 1'b1; wr_ptr_gray <= bin2gray(wr_ptr_bin + 1'b1); end end end // ---------------- read-side logic (da_clk domain) ---------------- // rd_en gating will use occupancy calculation reg rd_en_gated; wire [PTR_W-1:0] occupancy; // unsigned diff always @(posedge da_clk or negedge rst_n) begin if (!rst_n) begin rd_ptr_bin <= {PTR_W{1'b0}}; rd_ptr_gray <= {PTR_W{1'b0}}; wr_ptr_gray_sync1_rd <= {PTR_W{1'b0}}; wr_ptr_gray_sync2_rd <= {PTR_W{1'b0}}; wr_ptr_bin_sync_rd <= {PTR_W{1'b0}}; rd_en_gated <= 1'b0; end else begin // sync write pointer into read domain (two-stage) wr_ptr_gray_sync1_rd <= wr_ptr_gray; wr_ptr_gray_sync2_rd <= wr_ptr_gray_sync1_rd; // convert synchronized gray pointer to binary (registered conversion) wr_ptr_bin_sync_rd <= gray2bin_f(wr_ptr_gray_sync2_rd); // compute occupancy (unsigned arithmetic) // since both are PTR_W width, subtraction yields modulo behavior // occupancy = wr_ptr_bin_sync_rd - rd_ptr_bin // we compute occupancy combinationally in next always (but hold in reg here) // gating read: only when occupancy > SAFE_GUARD and not empty if ( ((wr_ptr_bin_sync_rd - rd_ptr_bin) > SAFE_GUARD) && (rd_ptr_gray != wr_ptr_gray_sync2_rd) ) begin // safe to read and not empty rd_en_gated <= 1'b1; rd_ptr_bin <= rd_ptr_bin + 1'b1; rd_ptr_gray <= bin2gray(rd_ptr_bin + 1'b1); end else begin rd_en_gated <= 1'b0; end end end // occupancy wire for observation/debug (optional) assign occupancy = (wr_ptr_bin_sync_rd - rd_ptr_bin); // ---------------- full / empty detection ---------------- // compute next write gray (for full detection) wire [PTR_W-1:0] wr_ptr_gray_next; assign wr_ptr_gray_next = bin2gray(wr_ptr_bin + 1'b1); // full: compare next write gray with read gray (synchronized into write domain) // MSB inversion trick for full detection assign full = (wr_ptr_gray_next == {~rd_ptr_gray_sync2_wr[PTR_W-1:PTR_W-2], rd_ptr_gray_sync2_wr[PTR_W-3:0]}); // empty: when read gray equals synchronized write gray in read domain assign empty = (rd_ptr_gray == wr_ptr_gray_sync2_rd); // ---------------- connect addresses to ram (lower ADDR_W bits) ---------------- wire [ADDR_W-1:0] wr_addr = wr_ptr_bin[ADDR_W-1:0]; wire [ADDR_W-1:0] rd_addr = rd_ptr_bin[ADDR_W-1:0]; // ---------------- ram instance (your existing IP) ---------------- wire [7:0] rd_data; ram_8_10 u_ram( .wr_data(wr_data), .wr_addr(wr_addr), .wr_en(wr_en_gated), .wr_clk(ad_clk), .wr_rst(!rst_n), .rd_data(rd_data), .rd_addr(rd_addr), .rd_clk(da_clk), .rd_rst(!rst_n) ); //ad out da_out u_da( .da_clk(da_clk), //i .rst_n(rst_n), //i .re_in(rd_data), //i .din_valid(rd_en_gated), //i .da_data(da_data) //o ); endmodule
最新发布
10-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值