Yii 1.1: jqrelcopy

Copies any DOM element and its children for usage in forms
41 followers

This extension is for usage in forms to copy or clone input elements or other DOM elements.

This is a wrapper for the jQuery plugin: relCopy

It's similar to the extension jappendo but easier to use and more flexible. Every clone can be removed by adding a remove link or icon.

Notes

  • Cloning datepicker is available since v1.1. Don't forget to delete the assets folder of the widget when upgrading to the new version.

  • See multimodelform if you need this functionality for clientside cloning records with batchUpdate/Insert/Delete at the server side. This extension will do the workaround discussed below for you.

Usage

  • Extract the files under .../protected/extensions
  • Add the widget code somewhere in the view

The simplest usage:

$this->widget('ext.jqrelcopy.JQRelcopy',
                 array(
                       'id' => 'copylink',
                       //'removeText' => 'remove' //uncomment to add remove link
                       );

All options:

$this->widget('ext.jqrelcopy.JQRelcopy',array(
 
 //the id of the 'Copy' link in the view, see below.
 'id' => 'copylink',
 
  //add a icon image tag instead of the text
  //leave empty to disable removing
 'removeText' => 'Remove',
 
 //htmlOptions of the remove link
 'removeHtmlOptions' => array('style'=>'color:red'),
 
 //options of the plugin, see http://www.andresvidal.com/labs/relcopy.html
 'options' => array(
 
       //A class to attach to each copy
      'copyClass'=>'newcopy',
 
      // The number of allowed copies. Default: 0 is unlimited
      'limit'=>5,
 
      //Option to clear each copies text input fields or textarea
      'clearInputs'=>true,
 
      //A jQuery selector used to exclude an element and its children
      'excludeSelector'=>'.skipcopy',
 
      //Additional HTML to attach at the end of each copy.
      'append'=>CHtml::tag('span',array('class'=>'hint'),'You can remove this line'),
   )
))
  • Add a 'Copy' link with the id, defined for the widget above. You have to add the attribute 'ref'. The value is a jquery-selector to define the element to copy. The code below will copy the div with the class 'copy'.
<a id="copylink" href="#" rel=".copy">Copy</a>
 
    <div class="row copy">
        <?php echo CHtml::label('Title',''); ?>
        <?php echo CHtml::textField('title[]','Title'); ?>
        <?php echo CHtml::textField('fld',"Don't copy",array('class'=>'skipcopy')); ?>
    </div>

Usage with date/time picker

Widgets needs a javascript workaround on cloning. We have to assign the CJuiDatePicker functionality to the cloned new element.

Since v1.1 there are the properties jsBeforeClone,jsAfterClone,jsBeforeNewId,jsAfterNewId available where javascript code can be implemented. Use 'this' as the current jQuery object.

For CJuiDatePicker and the extension extension datetimepicker there are predefined functions available, so it's easy to make cloning date fields work.

Save the config of the in a variable in the view.

$datePickerConfig =  array('name'=>'dayofbirth',
         'language'=>'de',
         'options'=>array(
            'showAnim'=>'fold',
          ));
 
   $this->widget('zii.widgets.jui.CJuiDatePicker',$datePickerConfig);

You have to assign the javascript code to the property 'jsAfterNewId'.

$this->widget('ext.jqrelcopy.JQRelcopy',
array(
      'id' => 'copylink',
      'removeText' => 'remove',
      //'jsBeforeNewId' => "alert(this.attr('id'));",
 
      //add the datapicker functionality to the cloned datepicker with the same options
      'jsAfterNewId' => JQRelcopy::afterNewIdDatePicker($datePickerConfig),
      ));

Support for 'datetimepicker' is analog (afterNewIdDateTimePicker).

For other widgets you have to find out the correct javascript code on cloning. Please let me know if you have found a javascript code for other widgets.

Note: I couldn't get Autocomplete working. Maybe one of you has an idea (see afterNewIdAutoComplete in JQRelcopy.php).

Resources

Projectpage of the jQuery plugin relCopy

Changelog

  • v1.1 Added support for cloning date/time widgets
  • v1.1.1 chrome issue: removeAttr, see comment from 'jackfiallos' below

Similar extensions

Total 20 comments

#16042 report it
Joblo at 2014/01/14 06:21am
clientside validation

If you are working with models, you should better use the extension multimodelform You can validate the models with the rules() of the model.

#16034 report it
prashant.tyagi at 2014/01/13 05:45am
how to apply client side validation to clone elements?

thanks for extension but i have a question how to apply client side validation to clone elements? thanks in advance

#12057 report it
Florent Gilliéron at 2013/02/25 09:42am
Probleme CJuiDatePicker in JQRelcopy

I have a problem with CJuiDatePicker in the module JQRelcopy.

I use this module as I have a form with a datepicker field to be copied as many times as the user wishes.

The module works fine if I put a normal field (without datepicker), but as soon as I add the module CJuiDatePicker which is also a module of the Yii framework, I have a blank page appears.

I study the problem and I saw that it was when I Atoute the following line in the properties of my widget JQRelcopy the problem occurs:

'jsAfterNewId' => JQRelcopy::afterNewIdDatePicker($datePickerConfig),

in

$this->widget('ext.jqrelcopy.JQRelcopy', array(
      'id' => 'copylink',
      'removeText' => 'remove',
      'jsAfterNewId' => JQRelcopy::afterNewIdDatePicker($datePickerConfig),
));

I look in several forums and anywhere a person has had the same problem as me.

Can you help me?

Sorry, for my English

#9926 report it
seniorboss at 2012/09/23 07:13am
An improvement

Hi to all, i've modified this great extension making an improvement. Now it's possible to insert the remove text inside an html tag. All was born for my need to insert the remove text inside a td tag of a table.

Istruction to apply the modify: 1) Add the following public member in the head of file JQRelcopy.php:

public $removeTextContainer = array();

2) modify the following code in the init function:

ORIGINAL:

if (!empty($this->removeText))
        {
            $onClick = '$(this).parent().remove(); return false;';
            $htmlOptions = array_merge($this->removeHtmlOptions,array('onclick'=>$onClick));
            $append = CHtml::link($this->removeText,'#',$htmlOptions);
 
            $this->options['append'] = empty($this->options['append']) ? $append : $append .' '.$this->options['append'];
        }

Replace with:

if (!empty($this->removeText))
        {
            $onClick = '$(this).parent().remove(); return false;';
            $htmlOptions = array_merge($this->removeHtmlOptions,array('onclick'=>$onClick));            
                        $append = "";
 
                        if(!empty($this->removeTextContainer)){
                            $htOpt = $this->removeTextContainer[1]==null ? array() : $this->removeTextContainer[1];
                            $closeTag = $this->removeTextContainer[2]==null ? false : $this->removeTextContainer[2];
                            $onClick = '$(this).parent().parent().remove(); return false;';
                            $htmlOptions = array_merge($this->removeHtmlOptions,array('onclick'=>$onClick));    
                            $append .= CHtml::tag($this->removeTextContainer[0],$htOpt,CHtml::link($this->removeText,'#',$htmlOptions),$closeTag);
 
                        }
                        else{
                            $append .= CHtml::link($this->removeText,'#',$htmlOptions);
                        }                                                
 
            $this->options['append'] = empty($this->options['append']) ? $append : $append .' '.$this->options['append'];
        }

3) in the config array of the widget, if you want to use this new option, declare the following attribute

//option to insert the remove text in a container insert by CHtml::tag
 //first parameter is the tag parameter of CHtml::tag
 //second parameter is the htmloption array of CHtmtl::tag
 //third paramater is the CloseTag parameter of CHtml::tag
 //the third parameter of CHtml::tag is not mapped because
 //were filled with the CHtml::link tag of Remove Button      
 
 'removeTextContainer'=>array("td",null,false),

Thank to all

Regards,

Seniorboss

#7507 report it
waitforit at 2012/03/27 01:13am
My Patched up JQrelcopy

Please see this Forum Post.

This enables JQrelcopy to create a uniqueID for each name attribute whether on update or create. It uses a regex to replace the contents of '[]' in model input names.

Example: input name="Model[$index][field]" id="Model_$index_field"

Therefore, when cloning a row of data you will get back an indexed array with each field of the model as an array key.

Example
Model:
0
field1
field2
field3

Credit to Ianare for the idea (I wasn't able to get his modified version working for my needs).

#6727 report it
phosItc at 2012/02/01 09:56am
Clone date

hello!! I try to use this extension that is good!! but I still have problem with datetimepicker I can't Clone date it just show me only the first row of form but the second row it not show Date calendar like the the first. Plz Explan more about this!! sorry I'm not good english for writting!! :)

#6632 report it
Afnan at 2012/01/23 12:14pm
Problem with fileField

I have been trying to solve it but :(

can you answer http://www.yiiframework.com/forum/index.php?/topic/28067-chtmlfilefield-with-jqrelcopy/

#5198 report it
Joblo at 2011/09/22 02:53am
import the class

This Yii errormessage tells, that the class 'JQRelcopy' cannot be found. You have to Yii::import('ext.jqrelcopy.JQRelcopy') in your view.

You need the afterNewIdDatePicker code, to make the duplicated datetimepicker edit, not the original.

Next time please comment in the forum about issues.

#5196 report it
lstrjstr at 2011/09/22 02:37am
no such file or directory

include(JQRelcopy.php) [function.include]: failed to open stream: No such file or directory

I got this problem when i try to put this code in my widget

'jsAfterNewId' => JQRelcopy::afterNewIdDatePicker($datePickerConfig),

but my jqrelcopy works for my datepicker. the problem is when i click on the duplicated datepicker, the original one is being edited.

#4975 report it
Jack Fiallos at 2011/09/02 02:08pm
A Bug to fix in jquery.relcopy.yii.1.0.js

Chrome has a little bug with checkbox fields .. so simply correct the 114 line

from

$(this).removeAttr('checked', '');

to

$(this).removeAttr('checked');
#4677 report it
traceshankar at 2011/08/03 12:48pm
unique id to cloned fields (dropdown box, text box)

Hi Guys,

Did anyone know how to assign new unique id's to cloned fields ? Appreciate your suggestions.

#4595 report it
traceshankar at 2011/07/25 05:33am
Cloning CJuiAutoComplete

Friends,

Did anyone manage to clone CJuiAutoComplete by using this extension ?

#4309 report it
ianaré at 2011/06/24 05:49am
now on git hub

I've put up my modifications to the extension up on github, for those interested.

https://github.com/digitick/yii-jqrelcopy

#4187 report it
ianaré at 2011/06/15 06:25am
using delegate

Me again ;-) I came across a problem when the copy button itself is manipulated by DOM modifications. Replacing the assignment

this.each(function() {
    $(this).click(function){
        ... CLICK FUNCTION ...
    }
);

with a delegate did the trick :

$('body').delegate("#"+$(this).attr('id'),"click", function(){
 ... CLICK FUNCTION ...
);
#4011 report it
Joblo at 2011/05/27 06:10am
Merging

Good news that you are still working on jqrelcopy. I'm looking forward to merge your code with the current existing.

#4010 report it
ianaré at 2011/05/27 05:52am
jui

I'm in the process of merging your improvements with my modified version of the extension.

It was simpler for me to implement the timepicker support because I also modified the extension to use a jquery delegate() binding, rather than having to recreate on each clone. Downside is that all the timepickers on the page will have the same settings ... but this is fine for my needs, I do need to be able to clone multiple timepickers at the same time.

I now have to get the autocomplete and comboboxes to work with the extension so if I find anything I'll keep you posted.

#3886 report it
Joblo at 2011/05/17 06:52pm
Cloning datepicker

ianare: Many thanks for your hint.

Now I was able to make cloning datepicker working in 'jqrelcopy' and 'multimodelform' Maybe you have an idea about CJuiAutoComplete. See the note above.

#3806 report it
ianaré at 2011/05/09 04:17am
getting datepicker to copy

To allow datepickers to be copied, the JS file needs this line in the main function (after « var clone .... ») :

// reset datepicker
$(clone).find(':input').removeClass("hasDatepicker");
#3750 report it
Joblo at 2011/05/04 04:50pm
Cloning autocomplete impossible

Sorry, it's impossible to clone a CJuiAutoComplete. The problem is the JQuery script in the jQuery's ready function.

jQuery('#autocomplete_name').autocomplete(...)

This part is not cloneable for the RelCopy plugin.

I can't see a way to produce

jQuery('#autocomplete_name2').autocomplete(...);
jQuery('#autocomplete_name3').autocomplete(...);
....

when the autocomplete input is cloned.

#3739 report it
traceshankar at 2011/05/04 01:52am
CJuiAutoComplete cloning issue

How to clone a CJuiAutoComplete widget by using this extension ? Any suggestions ?

Leave a comment

Please to leave your comment.

Create extension