@@ -23,6 +23,8 @@ def __init__(self, **kwargs):
2323 self ._options  =  None 
2424 self ._variable_name  =  None 
2525
26+  self ._random_slug  =  {}
27+ 
2628 self .callback  =  kwargs .get ('callback' , None )
2729 self .container  =  kwargs .get ('container' , None )
2830 self .options  =  kwargs .get ('options' , None )
@@ -54,6 +56,7 @@ def _jupyter_include_scripts(self):
5456 def  _jupyter_javascript (self , 
5557 global_options  =  None , 
5658 container  =  None ,
59+  random_slug  =  None ,
5760 retries  =  3 ,
5861 interval  =  1000 ):
5962 """Return the JavaScript code which Jupyter Labs will need to render the chart. 
@@ -68,6 +71,10 @@ def _jupyter_javascript(self,
6871 property if set, and ``'highcharts_target_div'`` if not set. 
6972 :type container: :class:`str <python:str>` or :obj:`None <python:None>` 
7073  
74+  :param random_slug: The random sequence of characters to append to the container name to ensure uniqueness. 
75+  Defaults to :obj:`None <python:None>` 
76+  :type random_slug: :class:`str <python:str>` or :obj:`None <python:None>` 
77+   
7178 :param retries: The number of times to retry rendering the chart. Used to avoid race conditions with the  
7279 Highcharts script. Defaults to 3. 
7380 :type retries: :class:`int <python:int>` 
@@ -79,35 +86,46 @@ def _jupyter_javascript(self,
7986 :rtype: :class:`str <python:str>` 
8087 """ 
8188 original_container  =  self .container 
82-  self .container  =  container  or  self .container  or  'highcharts_target_div' 
89+  new_container  =  container  or  self .container  or  'highcharts_target_div' 
90+  if  not  random_slug :
91+  self .container  =  new_container 
92+  else :
93+  self .container  =  f'{ new_container } { random_slug }  
8394
8495 if  global_options  is  not None :
8596 global_options  =  validate_types (global_options ,
8697 types  =  SharedOptions )
8798
8899 js_str  =  '' 
89100 js_str  +=  utility_functions .get_retryHighcharts ()
90- 
101+   
91102 if  global_options :
92103 js_str  +=  '\n '  +  utility_functions .prep_js_for_jupyter (global_options .to_js_literal ()) +  '\n ' 
93104
94105 js_str  +=  utility_functions .prep_js_for_jupyter (self .to_js_literal (),
95106 container  =  self .container ,
107+  random_slug  =  random_slug ,
96108 retries  =  retries ,
97109 interval  =  interval )
98110
99111 self .container  =  original_container 
100112
101113 return  js_str 
102114
103-  def  _jupyter_container_html (self , container  =  None ):
115+  def  _jupyter_container_html (self ,
116+  container  =  None ,
117+  random_slug  =  None ):
104118 """Returns the Jupyter Labs HTML container for rendering the chart in Jupyter Labs context. 
105119
106120 :param container: The ID to apply to the HTML container when rendered in Jupyter Labs. Defaults to 
107121 :obj:`None <python:None>`, which applies the :meth:`.container <highcharts_core.chart.Chart.container>`  
108122 property if set, and ``'highcharts_target_div'`` if not set. 
109123 :type container: :class:`str <python:str>` or :obj:`None <python:None>` 
110124
125+  :param random_slug: The random sequence of characters to append to the container/function name to ensure  
126+  uniqueness. Defaults to :obj:`None <python:None>` 
127+  :type random_slug: :class:`str <python:str>` or :obj:`None <python:None>` 
128+ 
111129 :rtype: :class:`str <python:str>` 
112130 """ 
113131 if  self .options .chart :
@@ -116,6 +134,8 @@ def _jupyter_container_html(self, container = None):
116134 height  =  400 
117135
118136 container  =  container  or  self .container  or  'highcharts_target_div' 
137+  if  random_slug :
138+  container  =  f'{ container } { random_slug }  
119139
120140 container_str  =  f"""<div id=\" { container } \"  style=\" width:100%; height:{ height } \" ></div>\n """ 
121141
@@ -426,6 +446,9 @@ def _copy_dict_key(cls,
426446 preserve_data  =  kwargs .get ('preserve_data' , True )
427447
428448 original_value  =  original [key ]
449+  if  other  is  None :
450+  other  =  {}
451+ 
429452 other_value  =  other .get (key , None )
430453
431454 if  key  ==  'data'  and  preserve_data :
@@ -525,9 +548,9 @@ def copy(self,
525548 :returns: A mutated version of ``other`` with new property values 
526549
527550 """ 
528-  super ().copy (other  =  other ,
529-  overwrite  =  overwrite ,
530-  ** kwargs )
551+  return   super ().copy (other  =  other ,
552+    overwrite  =  overwrite ,
553+    ** kwargs )
531554
532555 def  add_series (self , * series ):
533556 """Adds ``series`` to the 
@@ -666,6 +689,18 @@ def display(self,
666689 :param container: The ID to apply to the HTML container when rendered in Jupyter Labs. Defaults to 
667690 :obj:`None <python:None>`, which applies the :meth:`.container <highcharts_core.chart.Chart.container>`  
668691 property if set, and ``'highcharts_target_div'`` if not set. 
692+   
693+  .. note:: 
694+   
695+  Highcharts for Python will append a 6-character random string to the value of ``container`` 
696+  to ensure uniqueness of the chart's container when rendering in a Jupyter Notebook/Labs context. The 
697+  :class:`Chart <highcharts_core.chart.Chart>` instance will retain the mapping between container and the  
698+  random string so long as the instance exists, thus allowing you to easily update the rendered chart by 
699+  calling the :meth:`.display() <highcharts_core.chart.Chart.display>` method again. 
700+   
701+  If you wish to create a new chart from the instance that does not update the existing chart, then you can do 
702+  so by specifying a new ``container`` value. 
703+   
669704 :type container: :class:`str <python:str>` or :obj:`None <python:None>` 
670705
671706 :param retries: The number of times to retry rendering the chart. Used to avoid race conditions with the  
@@ -693,11 +728,21 @@ def display(self,
693728 include_display  =  display_mod .Javascript (data  =  include_js_str )
694729
695730 container  =  container  or  self .container  or  'highcharts_target_div' 
696-  html_str  =  self ._jupyter_container_html (container )
731+  if  not  self ._random_slug :
732+  self ._random_slug  =  {}
733+  
734+  random_slug  =  self ._random_slug .get (container , None )
735+  
736+  if  not  random_slug :
737+  random_slug  =  utility_functions .get_random_string ()
738+  self ._random_slug [container ] =  random_slug 
739+ 
740+  html_str  =  self ._jupyter_container_html (container , random_slug )
697741 html_display  =  display_mod .HTML (data  =  html_str )
698742
699743 chart_js_str  =  self ._jupyter_javascript (global_options  =  global_options , 
700744 container  =  container ,
745+  random_slug  =  random_slug ,
701746 retries  =  retries ,
702747 interval  =  interval )
703748 javascript_display  =  display_mod .Javascript (data  =  chart_js_str )
0 commit comments