Development

#2202: sfUJSPluginPatch.2.patch

You must first sign up to be able to contribute.

Ticket #2202: sfUJSPluginPatch.2.patch

File sfUJSPluginPatch.2.patch, 52.9 kB (added by haakeyar, 1 year ago)

Fixed a typo in my changes to the readme file.

  • plugins/sfUJSPlugin/config/config.php

    old new  
     1<?php 
     2sfRouting::getInstance()->prependRoute('ujs', '/UJS/script/key/:key.ujs', array('module' => 'sfUJS', 'action' => 'script')); 
  • plugins/sfUJSPlugin/lib/helper/UJSHelper.php

    old new  
    1 <?php 
    2  
    3 use_javascript('/sfUJSPlugin/js/jquery'); 
    4  
    5 /** 
    6  * Inserts JavaScript code unobtrusively 
    7  * 
    8  * <b>Example:</b> 
    9  * <code> 
    10  *  <?php UJS("alert('foobar');") ?> 
    11  * </code> 
    12  * 
    13  * @param  string JavaScript code 
    14  */ 
    15 function UJS($script) 
    16 
    17   $response = sfContext::getInstance()->getResponse(); 
    18   $response->setParameter('script', $response->getParameter('script', '', 'symfony/view/UJS').$script.";\n", 'symfony/view/UJS'); 
    19 
    20  
    21 /** 
    22  * Starts a JavaScript code block for unobtrusive insertion 
    23  * 
    24  * <b>Example:</b> 
    25  * <code> 
    26  *  <?php UJS_block() ?> 
    27  *    alert('foobar'); 
    28  *  <?php UJS_end_block() ?>  
    29  * </code> 
    30  * 
    31  * @see UJS_end_block 
    32  */ 
    33 function UJS_block() 
    34 
    35   ob_start(); 
    36   ob_implicit_flush(0); 
    37 
    38  
    39 /** 
    40  * Ends a JavaScript code block and inserts the JavaScript code unobtrusively 
    41  * 
    42  * @see UJS_block 
    43  */ 
    44 function UJS_end_block() 
    45 
    46   $content = ob_get_clean(); 
    47   UJS($content); 
    48 
    49  
    50 /** 
    51  * Gets a template-unique ID 
    52  * 
    53  * @return integer the incremental ID 
    54  */ 
    55  function UJS_incremental_id() 
    56 
    57   static $ujs_incremental_id = 0; 
    58   return 'UJS_'.$ujs_incremental_id++; 
    59 
    60  
    61 /** 
    62  * Inserts an invisible placeholder for adding something to the DOM with UJS afterwards 
    63  * 
    64  * @param string the id attribute of the placeholder 
    65  * 
    66  * @return string an HTML <span> tag  
    67  */ 
    68 function UJS_placeholder($id) 
    69 
    70   return content_tag('span', '', array('style' => 'display: none', 'class' => 'UJS_placeholder', 'id' => $id)); 
    71 
    72  
    73 /** 
    74  * Replaces an existing DOM element with some content unobtrusively 
    75  * 
    76  * <b>Example:</b> 
    77  * <code> 
    78  *  <?php UJS_replace('#foo', '<div>Hello, world!</div>') ?> 
    79  * </code> 
    80  * 
    81  * @param string the CSS3 selector to the DOM element(s) to replace 
    82  * @param string the HTML content to use for replacement 
    83  * 
    84  */ 
    85 function UJS_replace($selector, $html_code) 
    86 
    87   $html_code = preg_replace('/\r\n|\n|\r/', "\\n", $html_code); 
    88   $html_code = preg_replace("/'/", "\'", $html_code); 
    89   UJS(sprintf("jQuery('%s').after('%s');\$('%s').remove()", $selector, $html_code, $selector)); 
    90 
    91  
    92 /** 
    93  * Adds some some content unobtrusively 
    94  * 
    95  * <b>Example:</b> 
    96  * <code> 
    97  *  <?php UJS_write('<div>Hello, world!</div>') ?> 
    98  * </code> 
    99  * 
    100  * @param string the HTML content to use for insertion 
    101  * 
    102  */ 
    103 function UJS_write($html) 
    104 
    105   $id = UJS_incremental_id(); 
    106   UJS_replace("#".$id, $html); 
    107   echo UJS_placeholder($id); 
    108 
    109  
    110 /** 
    111  * Starts a HTML code block for unobtrusive content insertion 
    112  * 
    113  * <b>Example:</b> 
    114  * <code> 
    115  *  <?php UJS_write_block() ?> 
    116  *    <div>Hello, world!</div> 
    117  *  <?php UJS_end_write_block() ?>  
    118  * </code> 
    119  * 
    120  * @see UJS_end_write_block 
    121  */ 
    122 function UJS_write_block() 
    123 
    124   ob_start(); 
    125   ob_implicit_flush(0);   
    126 
    127  
    128 /** 
    129  * Ends a HTML code block for unobtrusive content insertion 
    130  * 
    131  * @see UJS_write_block 
    132  */ 
    133 function UJS_end_write_block() 
    134 
    135   $content = ob_get_clean(); 
    136   UJS_write($content); 
    137 
    138  
    139 /** 
    140  * Changes some attributes of an existing DOM element unobtrusively 
    141  * Alias for UJS_attr() 
    142  * 
    143  * @see UJS_attr 
    144  */ 
    145 function UJS_change_attributes($selector, $html_options = array()) 
    146 
    147     return UJS_attr($selector, $html_options); 
    148 
    149  
    150 /** 
    151  * Changes some attributes of an existing DOM element unobtrusively 
    152  * 
    153  * <b>Example:</b> 
    154  * <code> 
    155  *  <?php UJS_attr('#foo', array('class' => 'bar', 'alt' => 'foobar')) ?> 
    156  *  // You can also use the string syntax 
    157  *  <?php UJS_attr('#foo', 'class=bar alt=foobar') ?> 
    158  * </code> 
    159  * 
    160  * @param string the CSS3 selector to the DOM element(s) to replace 
    161  * @param array the element attributes to update 
    162  */ 
    163 function UJS_attr($selector, $html_options = array()) 
    164 
    165   $html_options = _parse_attributes($html_options); 
    166   $response = sfContext::getInstance()->getResponse(); 
    167   $script = $response->getParameter('script', '', 'symfony/view/UJS'); 
    168   $attributes = ''; 
    169   foreach($html_options as $key => $value) 
    170   { 
    171     $attributes .= sprintf(".attr('%s', '%s')", $key, $value); 
    172   } 
    173   $script .= sprintf("jQuery('%s')%s;\n", $selector, $attributes); 
    174   $response->setParameter('script', $script, 'symfony/view/UJS'); 
    175 
    176  
    177 /** 
    178  * Changes some style attributes of an existing DOM element unobtrusively 
    179  * Alias for UJS_css() 
    180  * 
    181  * @see UJS_css 
    182  */ 
    183 function UJS_change_style($selector, $css_options = array()) 
    184 
    185     return UJS_css($selector, $css_options); 
    186 
    187  
    188 /** 
    189  * Changes some style attributes of an existing DOM element unobtrusively 
    190  * 
    191  * <b>Example:</b> 
    192  * <code> 
    193  *  <?php UJS_attr('#foo', array('display' => 'none', 'text-decoration' => 'underline')) ?> 
    194  *  // You can also use the string syntax 
    195  *  <?php UJS_attr('#foo', 'display:none text-decoration:underline') ?> 
    196  * </code> 
    197  * 
    198  * @param string the CSS3 selector to the DOM element(s) to replace 
    199  * @param array the style attributes to update 
    200  */ 
    201 function UJS_css($selector, $css_options = array()) 
    202 
    203   if(is_string($css_options)) 
    204   { 
    205     preg_match_all('/ 
    206       \s*([\w-]+)             # key (may contain dash)            \\1 
    207       \s*:\s*                 # : 
    208       (\'|")?                 # values may be included in \' or " \\2 
    209       (.*?)                   # value                             \\3 
    210       (?(2) \\2)              # matching \' or " if needed        \\4 
    211       [\s;]*(?= 
    212         (?=[\w-]+\s*:) | \s*$  # followed by another key: or the end of the string 
    213       ) 
    214     /x', $css_options, $matches, PREG_SET_ORDER); 
    215     $css_options = array(); 
    216     foreach ($matches as $val) 
    217     { 
    218       $css_options[$val[1]] = sfToolkit::literalize($val[3]); 
    219     } 
    220   } 
    221  
    222   $response = sfContext::getInstance()->getResponse(); 
    223   $script = $response->getParameter('script', '', 'symfony/view/UJS'); 
    224   $attributes = ''; 
    225   foreach($css_options as $key => $value) 
    226   { 
    227     $attributes .= sprintf(".css('%s', '%s')", $key, $value); 
    228   } 
    229   $script .= sprintf("jQuery('%s')%s;\n", $selector, $attributes); 
    230   $response->setParameter('script', $script, 'symfony/view/UJS'); 
    231 
    232  
    233 /** 
    234  * Adds an event listener to an existing DOM element unobtrusively 
    235  * 
    236  * <b>Example:</b> 
    237  * <code> 
    238  *  <?php UJS_add_behaviour('#foo', 'click', "alert('foobar')") ?> 
    239  * </code> 
    240  * 
    241  * @param string the CSS3 selector to the DOM element(s) concerned by the behaviour 
    242  * @param string the event name (without leading 'on') 
    243  * @param string JavaScript code 
    244  */ 
    245 function UJS_add_behaviour($selector, $event, $script) 
    246 
    247   UJS(sprintf("jQuery('%s').%s(function() { %s })", $selector, $event, $script));   
    248 
    249  
    250 /** 
    251  * Inserts a link triggering a script unobtrusively 
    252  * 
    253  * <b>Example:</b> 
    254  * <code> 
    255  *  <?php echo UJS_link_to_function('click me', "alert('foo')", array('class' => 'bar')) ?> 
    256  *  // You can also use the string syntax 
    257  *  <?php echo UJS_link_to_function('click me', "alert('foo')", 'class=bar') ?> 
    258  * </code> 
    259  * 
    260  * @param string The text displayed in the link 
    261  * @param string JavaScript code 
    262  * @param array the <a> element attributes 
    263  * 
    264  * @return string An invisible HTML placeholder  
    265  */ 
    266 function UJS_link_to_function($name, $script, $html_options = array()) 
    267 
    268   $html_options = _parse_attributes($html_options); 
    269   $html_options['href'] = isset($html_options['href']) ? $html_options['href'] : '#'; 
    270   $html_options['onclick'] = $script.'; return false;'; 
    271   return UJS_write(content_tag('a', $name, $html_options, true)); 
    272 
    273  
    274 /** 
    275  * Inserts a button (input type=button) triggering a script unobtrusively 
    276  * 
    277  * <b>Example:</b> 
    278  * <code> 
    279  *  <?php echo UJS_button_to_function('click me', "alert('foo')", array('class' => 'bar')) ?> 
    280  *  // You can also use the string syntax 
    281  *  <?php echo UJS_button_to_function('click me', "alert('foo')", 'class=bar') ?> 
    282  * </code> 
    283  * 
    284  * @param string The text displayed in the button 
    285  * @param string JavaScript code 
    286  * @param array the <input> element attributes 
    287  * 
    288  * @return string An invisible HTML placeholder  
    289  */ 
    290 function UJS_button_to_function($name, $script, $html_options = array()) 
    291 
    292   $html_options = _parse_attributes($html_options); 
    293   $html_options['type'] = 'button'; 
    294   $html_options['value'] = $name; 
    295   $html_options['onclick'] = $script; 
    296   return UJS_write(tag('input', $html_options, false, true)); 
    297 
    298  
    299 /** 
    300  * Execute a remote action in the background using XMLHttpRequest 
    301  * defined by 'url' (using the 'url_for()' format)  
    302  * The result of that request can then be inserted into a 
    303  * DOM object whose selector can be specified with 'update'. 
    304  * Caution: This function is internal to the helper and does not produce UJS code 
    305  * 
    306  * Examples: 
    307  *  <?php echo _UJS_remote_function(array( 
    308  *    'update' => '#posts', 
    309  *    'url'    => 'destroy?id='.$post.id, 
    310  *  )) ?> 
    311  *  <?php echo _UJS_remote_function(array( 
    312  *    'update' => '#emails', 
    313  *    'url'    => '@list_emails', 
    314  *  )) ?> 
    315  * 
    316  * You can also specify a hash for 'update' to allow for 
    317  * easy redirection of output to an other DOM element if a server-side error occurs: 
    318  * 
    319  * Example: 
    320  *  <?php echo _UJS_remote_function(array( 
    321  *      'update' => array('success' => '#posts', 'failure' => '#error'), 
    322  *      'url'    => 'destroy?id='.$post.id, 
    323  *  )) ?> 
    324  * 
    325  * Optionally, you can use the 'position' parameter to influence 
    326  * how the target DOM element is updated. It must be one of 
    327  * 'before', 'top', 'bottom', or 'after'. 
    328  * 
    329  * Example: 
    330  *  <?php echo _UJS_remote_function(array( 
    331  *    'update'   => '#posts', 
    332  *    'position' => 'after', 
    333  *    'url'      => 'destroy?id='.$post.id, 
    334  *  )) ?> 
    335  * 
    336  * By default, these remote requests are processed asynchronous during 
    337  * which various JavaScript callbacks can be triggered (for progress indicators and 
    338  * the likes). All callbacks get access to the 'request' object, 
    339  * which holds the underlying XMLHttpRequest. 
    340  * 
    341  * To access the server response, use 'request.responseText', to 
    342  * find out the HTTP status, use 'request.status'. 
    343  * 
    344  * Example: 
    345  *  <?php echo link_to_remote($word, array( 
    346  *    'url'      => '@undo?n='.$word_counter, 
    347  *    'complete' => 'undoRequestCompleted(request)' 
    348  *  )) ?> 
    349  * 
    350  * The callbacks that may be specified are (in order): 
    351  * 
    352  * 'beforeSend'              Called before the XMLHttpRequest is executed. 
    353  *                           (synonyms: 'loading', 'loaded', 'interactive') 
    354  * 'success'                 Called when the XMLHttpRequest is completed, 
    355  *                           and the HTTP status code is in the 2XX range. 
    356  * 'error'                   Called when the XMLHttpRequest is completed, 
    357  *                           and the HTTP status code is not in the 2XX 
    358  *                           range. (synonym: 'failure') 
    359  * 'complete'                Called when the XMLHttpRequest is complete 
    360  *                           (fires after success/failure if they are present)., 
    361  * 
    362  * If you for some reason or another need synchronous processing (that'll 
    363  * block the browser while the request is happening), you can specify 
    364  * 'type' => 'synchronous'. 
    365  * 
    366  * You can customize further browser side call logic by passing 
    367  * in JavaScript code snippets via some optional parameters. In 
    368  * their order of use these are: 
    369  * 
    370  * 'confirm'             Adds confirmation dialog. 
    371  * 'condition'           Perform remote request conditionally 
    372  *                       by this expression. Use this to 
    373  *                       describe browser-side conditions when 
    374  *                       request should not be initiated. 
    375  * 
    376  * @param array Ajax parameters 
    377  */ 
    378 function _UJS_remote_function($options) 
    379 
    380   $condition    = ''; 
    381   $ajax_options = array(); 
    382    
    383   $ajax_options[] = "url: '".url_for($options['url'])."'"; 
    384    
    385   if (isset($options['position'])) 
    386   { 
    387     switch($options['position']) 
    388     { 
    389       case "before": 
    390         $update_position = 'before'; 
    391         break; 
    392       case "top": 
    393       case "prepend": 
    394         $update_position = 'prepend'; 
    395         break; 
    396       case "bottom": 
    397       case "append": 
    398         $update_position = 'append'; 
    399         break; 
    400       case "after": 
    401         $update_position = 'after'; 
    402         break; 
    403       default: 
    404         $update_position = 'html'; 
    405     } 
    406   } 
    407   else 
    408   { 
    409     $update_position = 'html'; 
    410   } 
    411  
    412   if (isset($options['type']) && $options['type'] == "synchronous") 
    413   { 
    414     $ajax_options[] = "async: false"; 
    415   } 
    416  
    417   if (isset($options['type']) && $options['type'] != "synchronous" && $options['type'] != "asynchronous") 
    418   { 
    419     $ajax_options[] = "type: ".strtoupper($options['type']); 
    420   } 
    421   else if (isset($options['method'])) 
    422   { 
    423     $ajax_options[] = "type: ".strtoupper($options['method']); 
    424   } 
    425  
    426   if (isset($options['with'])) 
    427   { 
    428     $ajax_options[] = "data: ".$options['with']; 
    429   } 
    430   else if (isset($options['data'])) 
    431   { 
    432     $ajax_options[] = "data: ".$options['data']; 
    433   } 
    434  
    435   if (isset($options['update']) && is_array($options['update'])) 
    436   { 
    437     if (isset($options['update']['success'])) 
    438     { 
    439       $ajax_options[] = "success: function(response) { jQuery('".$options['update']['success']."').".$update_position."(response) }"; 
    440     } 
    441     if (isset($options['update']['failure'])) 
    442     { 
    443       $ajax_options[] = "error: function(response) { jQuery('".$options['update']['failure']."').".$update_position."(response.responseText) }"; 
    444     } 
    445   } 
    446   else if (isset($options['update'])) 
    447   { 
    448     $ajax_options[] = "success: function(response) { jQuery('".$options['update']."').".$update_position."(response) }"; 
    449   } 
    450   else if (isset($options['success'])) 
    451   { 
    452     $ajax_options[] = "success: function(response) { jQuery('".$options['success']."').".$update_position."(response) }"; 
    453   } 
    454    
    455   if (isset($options['confirm'])) 
    456   { 
    457     $condition .= "if(confirm('".$options['confirm']."')) "; 
    458   } 
    459   if (isset($options['condition'])) 
    460   { 
    461     $condition .= "if(".$options['condition'].") "; 
    462   } 
    463    
    464   return $condition."jQuery.ajax({".join(', ', $ajax_options)."})"; 
    465 
    466  
    467 /** 
    468  * Transforms a regular link (or button) into an Ajax one unobtrusively 
    469  * 
    470  * @param string the CSS3 selector to the DOM element(s) concerned by the behaviour 
    471  * @param array Hash of Ajax options (see _UJS_remote_function for details) 
    472  * 
    473  * @see _UJS_remote_function  
    474  */ 
    475 function UJS_ajaxify_link($selector, $ajax) 
    476 
    477   UJS(sprintf("jQuery('%s').click(function() { %s; return false })", $selector, _UJS_remote_function($ajax)));   
    478 
    479  
    480 /** 
    481  * Transforms a form into an Ajax one unobtrusively 
    482  * 
    483  * @param string the CSS3 selector to the DOM element(s) concerned by the behaviour 
    484  * @param array Hash of Ajax options (see _UJS_remote_function for details) 
    485  * 
    486  * @see _UJS_remote_function  
    487  */ 
    488 function UJS_ajaxify_form($selector, $ajax) 
    489 
    490   UJS(sprintf("jQuery('%s').submit(function() { %s; return false })", $selector, _UJS_remote_function($ajax)));   
    491 
    492  
    493 /** 
    494  * Transforms a link, a button or form into an Ajax one unobtrusively 
    495  * 
    496  * @param string the CSS3 selector to the DOM element(s) concerned by the behaviour 
    497  * @param array Hash of Ajax options (see _UJS_remote_function for details) 
    498  * 
    499  * @see _UJS_remote_function  
    500  */ 
    501 function UJS_ajaxify($selector, $ajax) 
    502 
    503   $UJS = "elements = jQuery('%s');"; 
    504   $UJS .= "if(elements.is('form')) handler = 'submit'; else handler = 'click'; "; 
    505   $UJS .= "elements.bind(handler, function() { %s; return false }); "; 
    506   UJS(sprintf($UJS, $selector, _UJS_remote_function($ajax)));  
    507 
    508  
    509 /** 
    510  * Defines how the UJS code is added for the current request 
    511  * 
    512  * @param boolean True for static code (attached in another file), false for code embedded in the response contents 
    513  */ 
    514 function UJS_set_inclusion($static = true) 
    515 
    516   sfContext::getInstance()->getResponse()->setParameter('static', $static, 'symfony/view/UJS'); 
    517 
    518  
    519 /** 
    520  * Returns previously added UJS code 
    521  * The static setting can be set in three places: 
    522  *  - as a parameter to the get_UJS() helper 
    523  *  - as a parameter of the response object (name 'static', namespace 'symfony/view/UJS') 
    524  *  - as a settings of the app.yml (name 'app_UJSPlugin_static') 
    525  * The default value is true 
    526  * 
    527  * @param boolean True for static code (attached in another file), false otherwise (default) 
    528  * 
    529  * @return string if $static=false, a JavaScript code block 
    530  */ 
    531 function get_UJS($static = null) 
    532 
    533   $response = sfContext::getInstance()->getResponse(); 
    534   $response->setParameter('included', true, 'symfony/view/UJS'); 
    535    
    536   if(is_null($static)) 
    537   { 
    538     if(is_null($response_static = $response->getParameter('static', null, 'symfony/view/UJS'))) 
    539     { 
    540       $static = sfConfig::get('app_UJSPlugin_static', true); 
    541     } 
    542     else 
    543     { 
    544       $static = $response_static; 
    545     } 
    546   } 
    547   if ($UJS = $response->getParameter('script', false, 'symfony/view/UJS')) 
    548   { 
    549       $code = sprintf("jQuery(document).ready(function(){\n%s })", $UJS); 
    550       if($static) 
    551       { 
    552       // JavaScript code is in another file 
    553       use_helper('PJS'); 
    554       $key = md5(sfRouting::getInstance()->getCurrentInternalUri()); 
    555       sfContext::getInstance()->getUser()->setAttribute('UJS_'.$key, $code, 'symfony/UJS'); 
    556       use_pjs('sfUJS/script?key='.$key); 
    557     } 
    558     else 
    559     { 
    560       // JavaScript code appears in the document 
    561       return sprintf("<script type=\"text/javascript\">\n//  <![CDATA[\n%s\n//  ]]>\n</script>", $code); 
    562     } 
    563   } 
    564   return ''; 
    565 
    566  
    567 /** 
    568  * Prints previously added UJS code 
    569  * 
    570  * @param boolean True for static code (attached in another file), false otherwise (default) 
    571  * 
    572  */ 
    573 function include_UJS($static = false) 
    574 
    575   echo get_UJS($static); 
    576 
     1<?php 
     2 
     3use_javascript('/sfUJSPlugin/js/jquery'); 
     4 
     5/** 
     6 * Inserts JavaScript code unobtrusively 
     7 * 
     8 * <b>Example:</b> 
     9 * <code> 
     10 *  <?php UJS("alert('foobar');") ?> 
     11 * </code> 
     12 * 
     13 * @param  string JavaScript code 
     14 */ 
     15function UJS($script) 
     16
     17  sfUJS::getInstance()->addUJS($script); 
     18
     19 
     20/** 
     21 * Starts a JavaScript code block for unobtrusive insertion 
     22 * 
     23 * <b>Example:</b> 
     24 * <code> 
     25 *  <?php UJS_block() ?> 
     26 *    alert('foobar'); 
     27 *  <?php UJS_end_block() ?>  
     28 * </code> 
     29 * 
     30 * @see UJS_end_block 
     31 */ 
     32function UJS_block() 
     33
     34  ob_start(); 
     35  ob_implicit_flush(0); 
     36
     37 
     38/** 
     39 * Ends a JavaScript code block and inserts the JavaScript code unobtrusively 
     40 * 
     41 * @see UJS_block 
     42 */ 
     43function UJS_end_block() 
     44
     45  $content = ob_get_clean(); 
     46  UJS($content); 
     47
     48 
     49/** 
     50 * Gets a template-unique ID 
     51 * 
     52 * @return integer the incremental ID 
     53 */ 
     54 function UJS_incremental_id() 
     55
     56  static $ujs_incremental_id = 0; 
     57  return 'UJS_'.$ujs_incremental_id++; 
     58
     59 
     60/** 
     61 * Inserts an invisible placeholder for adding something to the DOM with UJS afterwards 
     62 * 
     63 * @param string the id attribute of the placeholder 
     64 * 
     65 * @return string an HTML <span> tag  
     66 */ 
     67function UJS_placeholder($id) 
     68
     69  return content_tag('span', '', array('style' => 'display: none', 'class' => 'UJS_placeholder', 'id' => $id)); 
     70
     71 
     72/** 
     73 * Replaces an existing DOM element with some content unobtrusively 
     74 * 
     75 * <b>Example:</b> 
     76 * <code> 
     77 *  <?php UJS_replace('#foo', '<div>Hello, world!</div>') ?> 
     78 * </code> 
     79 * 
     80 * @param string the CSS3 selector to the DOM element(s) to replace 
     81 * @param string the HTML content to use for replacement 
     82 * 
     83 */ 
     84function UJS_replace($selector, $html_code) 
     85
     86  $html_code = preg_replace('/\r\n|\n|\r/', "\\n", $html_code); 
     87  $html_code = preg_replace("/'/", "\'", $html_code); 
     88  UJS(sprintf("jQuery('%s').after('%s');\$('%s').remove()", $selector, $html_code, $selector)); 
     89
     90 
     91/** 
     92 * Adds some some content unobtrusively 
     93 * 
     94 * <b>Example:</b> 
     95 * <code> 
     96 *  <?php UJS_write('<div>Hello, world!</div>') ?> 
     97 * </code> 
     98 * 
     99 * @param string the HTML content to use for insertion 
     100 * 
     101 */ 
     102function UJS_write($html) 
     103
     104  $id = UJS_incremental_id(); 
     105  UJS_replace("#".$id, $html); 
     106  echo UJS_placeholder($id); 
     107
     108 
     109/** 
     110 * Starts a HTML code block for unobtrusive content insertion 
     111 * 
     112 * <b>Example:</b> 
     113 * <code> 
     114 *  <?php UJS_write_block() ?> 
     115 *    <div>Hello, world!</div> 
     116 *  <?php UJS_end_write_block() ?>  
     117 * </code> 
     118 * 
     119 * @see UJS_end_write_block 
     120 */ 
     121function UJS_write_block() 
     122
     123  ob_start(); 
     124  ob_implicit_flush(0);   
     125
     126 
     127/** 
     128 * Ends a HTML code block for unobtrusive content insertion 
     129 * 
     130 * @see UJS_write_block 
     131 */ 
     132function UJS_end_write_block() 
     133
     134  $content = ob_get_clean(); 
     135  UJS_write($content); 
     136
     137 
     138/** 
     139 * Changes some attributes of an existing DOM element unobtrusively 
     140 * Alias for UJS_attr() 
     141 * 
     142 * @see UJS_attr 
     143 */ 
     144function UJS_change_attributes($selector, $html_options = array()) 
     145
     146    return UJS_attr($selector, $html_options); 
     147
     148 
     149/** 
     150 * Changes some attributes of an existing DOM element unobtrusively 
     151 * 
     152 * <b>Example:</b> 
     153 * <code> 
     154 *  <?php UJS_attr('#foo', array('class' => 'bar', 'alt' => 'foobar')) ?> 
     155 *  // You can also use the string syntax 
     156 *  <?php UJS_attr('#foo', 'class=bar alt=foobar') ?> 
     157 * </code> 
     158 * 
     159 * @param string the CSS3 selector to the DOM element(s) to replace 
     160 * @param array the element attributes to update 
     161 */ 
     162function UJS_attr($selector, $html_options = array()) 
     163
     164  $html_options = _parse_attributes($html_options); 
     165  $attributes = ''; 
     166  foreach($html_options as $key => $value) 
     167  { 
     168    $attributes .= sprintf(".attr('%s', '%s')", $key, $value); 
     169  } 
     170  $script = sprintf("jQuery('%s')%s;\n", $selector, $attributes); 
     171  sfUJS::getInstance()->addUJS($script); 
     172
     173 
     174/** 
     175 * Changes some style attributes of an existing DOM element unobtrusively 
     176 * Alias for UJS_css() 
     177 * 
     178 * @see UJS_css 
     179 */ 
     180function UJS_change_style($selector, $css_options = array()) 
     181
     182    return UJS_css($selector, $css_options); 
     183
     184 
     185/** 
     186 * Changes some style attributes of an existing DOM element unobtrusively 
     187 * 
     188 * <b>Example:</b> 
     189 * <code> 
     190 *  <?php UJS_attr('#foo', array('display' => 'none', 'text-decoration' => 'underline')) ?> 
     191 *  // You can also use the string syntax 
     192 *  <?php UJS_attr('#foo', 'display:none text-decoration:underline') ?> 
     193 * </code> 
     194 * 
     195 * @param string the CSS3 selector to the DOM element(s) to replace 
     196 * @param array the style attributes to update 
     197 */ 
     198function UJS_css($selector, $css_options = array()) 
     199
     200  if(is_string($css_options)) 
     201  { 
     202    preg_match_all('/ 
     203      \s*([\w-]+)             # key (may contain dash)            \\1 
     204      \s*:\s*                 # : 
     205      (\'|")?                 # values may be included in \' or " \\2 
     206      (.*?)                   # value                             \\3 
     207      (?(2) \\2)              # matching \' or " if needed        \\4 
     208      [\s;]*(?= 
     209        (?=[\w-]+\s*:) | \s*$  # followed by another key: or the end of the string 
     210      ) 
     211    /x', $css_options, $matches, PREG_SET_ORDER); 
     212    $css_options = array(); 
     213    foreach ($matches as $val) 
     214    { 
     215      $css_options[$val[1]] = sfToolkit::literalize($val[3]); 
     216    } 
     217  } 
     218 
     219  $attributes = ''; 
     220  foreach($css_options as $key => $value) 
     221  { 
     222    $attributes .= sprintf(".css('%s', '%s')", $key, $value); 
     223  } 
     224  $script = sprintf("jQuery('%s')%s;\n", $selector, $attributes); 
     225  sfUJS::getInstance()->addUJS($script); 
     226
     227 
     228/** 
     229 * Adds an event listener to an existing DOM element unobtrusively 
     230 * 
     231 * <b>Example:</b> 
     232 * <code> 
     233 *  <?php UJS_add_behaviour('#foo', 'click', "alert('foobar')") ?> 
     234 * </code> 
     235 * 
     236 * @param string the CSS3 selector to the DOM element(s) concerned by the behaviour 
     237 * @param string the event name (without leading 'on') 
     238 * @param string JavaScript code 
     239 */ 
     240function UJS_add_behaviour($selector, $event, $script) 
     241
     242  UJS(sprintf("jQuery('%s').%s(function() { %s })", $selector, $event, $script));   
     243
     244 
     245/** 
     246 * Inserts a link triggering a script unobtrusively 
     247 * 
     248 * <b>Example:</b> 
     249 * <code> 
     250 *  <?php echo UJS_link_to_function('click me', "alert('foo')", array('class' => 'bar')) ?> 
     251 *  // You can also use the string syntax 
     252 *  <?php echo UJS_link_to_function('click me', "alert('foo')", 'class=bar') ?> 
     253 * </code> 
     254 * 
     255 * @param string The text displayed in the link 
     256 * @param string JavaScript code 
     257 * @param array the <a> element attributes 
     258 * 
     259 * @return string An invisible HTML placeholder  
     260 */ 
     261function UJS_link_to_function($name, $script, $html_options = array()) 
     262
     263  $html_options = _parse_attributes($html_options); 
     264  $html_options['href'] = isset($html_options['href']) ? $html_options['href'] : '#'; 
     265  $html_options['onclick'] = $script.'; return false;'; 
     266  return UJS_write(content_tag('a', $name, $html_options, true)); 
     267
     268 
     269/** 
     270 * Inserts a button (input type=button) triggering a script unobtrusively 
     271 * 
     272 * <b>Example:</b> 
     273 * <code> 
     274 *  <?php echo UJS_button_to_function('click me', "alert('foo')", array('class' => 'bar')) ?> 
     275 *  // You can also use the string syntax 
     276 *  <?php echo UJS_button_to_function('click me', "alert('foo')", 'class=bar') ?> 
     277 * </code> 
     278 * 
     279 * @param string The text displayed in the button 
     280 * @param string JavaScript code 
     281 * @param array the <input> element attributes 
     282 * 
     283 * @return string An invisible HTML placeholder  
     284 */ 
     285function UJS_button_to_function($name, $script, $html_options = array()) 
     286
     287  $html_options = _parse_attributes($html_options); 
     288  $html_options['type'] = 'button'; 
     289  $html_options['value'] = $name; 
     290  $html_options['onclick'] = $script; 
     291  return UJS_write(tag('input', $html_options, false, true)); 
     292
     293 
     294/** 
     295 * Execute a remote action in the background using XMLHttpRequest 
     296 * defined by 'url' (using the 'url_for()' format)  
     297 * The result of that request can then be inserted into a 
     298 * DOM object whose selector can be specified with 'update'. 
     299 * Caution: This function is internal to the helper and does not produce UJS code 
     300 * 
     301 * Examples: 
     302 *  <?php echo _UJS_remote_function(array( 
     303 *    'update' => '#posts', 
     304 *    'url'    => 'destroy?id='.$post.id, 
     305 *  )) ?> 
     306 *  <?php echo _UJS_remote_function(array( 
     307 *    'update' => '#emails', 
     308 *    'url'    => '@list_emails', 
     309 *  )) ?> 
     310 * 
     311 * You can also specify a hash for 'update' to allow for 
     312 * easy redirection of output to an other DOM element if a server-side error occurs: 
     313 * 
     314 * Example: 
     315 *  <?php echo _UJS_remote_function(array( 
     316 *      'update' => array('success' => '#posts', 'failure' => '#error'), 
     317 *      'url'    => 'destroy?id='.$post.id, 
     318 *  )) ?> 
     319 * 
     320 * Optionally, you can use the 'position' parameter to influence 
     321 * how the target DOM element is updated. It must be one of 
     322 * 'before', 'top', 'bottom', or 'after'. 
     323 * 
     324 * Example: 
     325 *  <?php echo _UJS_remote_function(array( 
     326 *    'update'   => '#posts', 
     327 *    'position' => 'after', 
     328 *    'url'      => 'destroy?id='.$post.id, 
     329 *  )) ?> 
     330 * 
     331 * By default, these remote requests are processed asynchronous during 
     332 * which various JavaScript callbacks can be triggered (for progress indicators and 
     333 * the likes). All callbacks get access to the 'request' object, 
     334 * which holds the underlying XMLHttpRequest. 
     335 * 
     336 * To access the server response, use 'request.responseText', to 
     337 * find out the HTTP status, use 'request.status'. 
     338 * 
     339 * Example: 
     340 *  <?php echo link_to_remote($word, array( 
     341 *    'url'      => '@undo?n='.$word_counter, 
     342 *    'complete' => 'undoRequestCompleted(request)' 
     343 *  )) ?> 
     344 * 
     345 * The callbacks that may be specified are (in order): 
     346 * 
     347 * 'beforeSend'              Called before the XMLHttpRequest is executed. 
     348 *                           (synonyms: 'loading', 'loaded', 'interactive') 
     349 * 'success'                 Called when the XMLHttpRequest is completed, 
     350 *                           and the HTTP status code is in the 2XX range. 
     351 * 'error'                   Called when the XMLHttpRequest is completed, 
     352 *                           and the HTTP status code is not in the 2XX 
     353 *                           range. (synonym: 'failure') 
     354 * 'complete'                Called when the XMLHttpRequest is complete 
     355 *                           (fires after success/failure if they are present)., 
     356 * 
     357 * If you for some reason or another need synchronous processing (that'll 
     358 * block the browser while the request is happening), you can specify 
     359 * 'type' => 'synchronous'. 
     360 * 
     361 * You can customize further browser side call logic by passing 
     362 * in JavaScript code snippets via some optional parameters. In 
     363 * their order of use these are: 
     364 * 
     365 * 'confirm'             Adds confirmation dialog. 
     366 * 'condition'           Perform remote request conditionally 
     367 *                       by this expression. Use this to 
     368 *                       describe browser-side conditions when 
     369 *                       request should not be initiated. 
     370 * 
     371 * @param array Ajax parameters 
     372 */ 
     373function _UJS_remote_function($options) 
     374
     375  $condition    = ''; 
     376  $ajax_options = array(); 
     377   
     378  $ajax_options[] = "url: '".url_for($options['url'])."'"; 
     379   
     380  if (isset($options['position'])) 
     381  { 
     382    switch($options['position']) 
     383    { 
     384      case "before": 
     385        $update_position = 'before'; 
     386        break; 
     387      case "top": 
     388      case "prepend": 
     389        $update_position = 'prepend'; 
     390        break; 
     391      case "bottom": 
     392      case "append": 
     393        $update_position = 'append'; 
     394        break; 
     395      case "after": 
     396        $update_position = 'after'; 
     397        break; 
     398      default: 
     399        $update_position = 'html'; 
     400    } 
     401  } 
     402  else 
     403  { 
     404    $update_position = 'html'; 
     405  } 
     406 
     407  if (isset($options['type']) && $options['type'] == "synchronous") 
     408  { 
     409    $ajax_options[] = "async: false"; 
     410  } 
     411 
     412  if (isset($options['type']) && $options['type'] != "synchronous" && $options['type'] != "asynchronous") 
     413  { 
     414    $ajax_options[] = "type: ".strtoupper($options['type']); 
     415  } 
     416  else if (isset($options['method'])) 
     417  { 
     418    $ajax_options[] = "type: ".strtoupper($options['method']); 
     419  } 
     420 
     421  if (isset($options['with'])) 
     422  { 
     423    $ajax_options[] = "data: ".$options['with']; 
     424  } 
     425  else if (isset($options['data'])) 
     426  { 
     427    $ajax_options[] = "data: ".$options['data']; 
     428  } 
     429 
     430  if (isset($options['update']) && is_array($options['update'])) 
     431  { 
     432    if (isset($options['update']['success'])) 
     433    { 
     434      $ajax_options[] = "success: function(response) { jQuery('".$options['update']['success']."').".$update_position."(response) }"; 
     435    } 
     436    if (isset($options['update']['failure'])) 
     437    { 
     438      $ajax_options[] = "error: function(response) { jQuery('".$options['update']['failure']."').".$update_position."(response.responseText) }"; 
     439    } 
     440  } 
     441  else if (isset($options['update'])) 
     442  { 
     443    $ajax_options[] = "success: function(response) { jQuery('".$options['update']."').".$update_position."(response) }"; 
     444  } 
     445  else if (isset($options['success'])) 
     446  { 
     447    $ajax_options[] = "success: function(response) { jQuery('".$options['success']."').".$update_position."(response) }"; 
     448  } 
     449   
     450  if (isset($options['confirm'])) 
     451  { 
     452    $condition .= "if(confirm('".$options['confirm']."')) "; 
     453  } 
     454  if (isset($options['condition'])) 
     455  { 
     456    $condition .= "if(".$options['condition'].") "; 
     457  } 
     458   
     459  return $condition."jQuery.ajax({".join(', ', $ajax_options)."})"; 
     460
     461 
     462/** 
     463 * Transforms a regular link (or button) into an Ajax one unobtrusively 
     464 * 
     465 * @param string the CSS3 selector to the DOM element(s) concerned by the behaviour 
     466 * @param array Hash of Ajax options (see _UJS_remote_function for details) 
     467 * 
     468 * @see _UJS_remote_function  
     469 */ 
     470function UJS_ajaxify_link($selector, $ajax) 
     471
     472  UJS(sprintf("jQuery('%s').click(function() { %s; return false })", $selector, _UJS_remote_function($ajax)));   
     473
     474 
     475/** 
     476 * Transforms a form into an Ajax one unobtrusively 
     477 * 
     478 * @param string the CSS3 selector to the DOM element(s) concerned by the behaviour 
     479 * @param array Hash of Ajax options (see _UJS_remote_function for details) 
     480 * 
     481 * @see _UJS_remote_function  
     482 */ 
     483function UJS_ajaxify_form($selector, $ajax) 
     484
     485  UJS(sprintf("jQuery('%s').submit(function() { %s; return false })", $selector, _UJS_remote_function($ajax)));   
     486
     487 
     488/** 
     489 * Transforms a link, a button or form into an Ajax one unobtrusively 
     490 * 
     491 * @param string the CSS3 selector to the DOM element(s) concerned by the behaviour 
     492 * @param array Hash of Ajax options (see _UJS_remote_function for details) 
     493 * 
     494 * @see _UJS_remote_function  
     495 */ 
     496function UJS_ajaxify($selector, $ajax) 
     497
     498  $UJS = "elements = jQuery('%s');"; 
     499  $UJS .= "if(elements.is('form')) handler = 'submit'; else handler = 'click'; "; 
     500  $UJS .= "elements.bind(handler, function() { %s; return false }); "; 
     501  UJS(sprintf($UJS, $selector, _UJS_remote_function($ajax)));  
     502
     503 
     504/** 
     505 * Defines how the UJS code is added for the current request 
     506 * 
     507 * @param boolean True for static code (attached in another file), false for code embedded in the response contents 
     508 */ 
     509function UJS_set_inclusion($static = true) 
     510
     511  sfUJS::getInstance()->setStatic($static); 
     512
     513 
     514function include_ujs($static=null) 
     515
     516  $ujs = sfUJS::getInstance(); 
     517  if(!is_null($static)) 
     518    $ujs->setStatic($static); 
     519  if($ujs->isStatic() && $ujs->saveToCache()) 
     520  { 
     521    // The JavaScript is static and it got saved to the cache without problems 
     522    echo '<script type="text/javascript" src="'.htmlentities(url_for('sfUJS/script?key='.$ujs->getKey())).'"></script>'; 
     523  } 
     524  else 
     525  { 
     526    // The JavaScript is not static or it didn't get saved to the cache 
     527    echo sprintf("<script type=\"text/javascript\">\n//  <![CDATA[\n%s\n//  ]]>\n</script>", $ujs->getFinishedUjs()); 
     528  } 
     529  $ujs->cleanUJS(); // Clean the UJS, so that it is not re-included in the filter 
     530
     531 
  • plugins/sfUJSPlugin/lib/sfUJS.class.php

    old new  
     1<?php 
     2/** 
     3 * sfUJS is used to combine the ujs and save it to the cache. 
     4 *  
     5 * Singleton. Use sfUJS::getInstance() to get the current instance. 
     6 * The static methods are used to fetch the UJS from the cache and display it. 
     7 */ 
     8class sfUJS 
     9{ 
     10  /** 
     11   * The instance created by sfUJS::getInstance(). 
     12   * 
     13   * @var sfUJS The current instance 
     14   */ 
     15  protected static $instance; 
     16  /** 
     17   * Whether the should be static 
     18   *  
     19   * @var boolean 
     20   */ 
     21  protected $isStatic; 
     22  /** 
     23   * The ujs buffer. 
     24   *  
     25   * @var string The ujs 
     26   */ 
     27  protected $ujs = ''; 
     28  /** 
     29   * The cache key used in the cache (md5-hash of the UJS) 
     30   * @var string 
     31   */ 
     32  protected $key; 
     33   
     34  /** 
     35   * Get the current instance of this singleton. 
     36   * 
     37   * @return sfUJS The current instance of sfUJS 
     38   */ 
     39  public static function getInstance() 
     40  { 
     41    if(is_object(self::$instance)) 
     42      return self::$instance; 
     43    else 
     44      return self::$instance = new sfUJS(); 
     45  } 
     46  /** 
     47   * Checks whether an instance of this singleton is created. 
     48   * @return boolean True if there is an instance. 
     49   */ 
     50  public static function hasInstance() 
     51  { 
     52    return is_object(self::$instance); 
     53  } 
     54  protected function __construct() 
     55  { 
     56  } 
     57   
     58  /** 
     59   * Add some unobtrusive JavaScript to the buffer 
     60   * 
     61   * @param string $js JavaScript to be added 
     62   */ 
     63  public function addUJS($js) 
     64  { 
     65    $this->ujs .= $js.";\n"; 
     66  } 
     67  /** 
     68   * Checks if any unobtrusive JavaScript is saved to the buffer 
     69   *  
     70   * @return boolean True if there is any UJS. 
     71   */ 
     72  public function hasUJS() 
     73  { 
     74    return (strlen($this->ujs) > 0); 
     75  } 
     76  /** 
     77   * Removes the UJS from the buffer. 
     78   *  
     79   * Clean the UJS after including it to avoid re-including the same UJS 
     80   */ 
     81  public function cleanUJS() 
     82  { 
     83    $this->ujs = ''; 
     84  } 
     85 /** 
     86  * Get the finished UJS-code, wrapped in "jQuery(document.ready(function(){\n[...] })", ready to be printed in a script-tag 
     87  *  
     88  * @return string The finished UJS-code 
     89  */ 
     90  public function getFinishedUjs() 
     91  { 
     92    // Could possibly compress the cache with some kind of a JavaScript compressor here. 
     93    return 'jQuery(document).ready(function(){'."\n".$this->ujs.' })'; 
     94  } 
     95   
     96  public function __toString() 
     97  { 
     98    return $this->getFinishedUjs(); 
     99  } 
     100   
     101  /** 
     102   * Initialize the Cache, using the configuration from app.yml, or the default configuration. 
     103   *  
     104   * Does not use sf_factory_view_cache, because sfConfig::get('sf_factory_view_cache') returns null. 
     105   * Actually, sfConfig::getAll() doesn't return anything from sf_factory. It's probably not supposed to. 
     106   *  
     107   * @return sfCache The initialized cache class.  
     108   */ 
     109  public static function initCache() 
     110  { 
     111    $cacheConfig = sfConfig::get('app_UJSPlugin_cache', array( 
     112      'class' => 'sfFileCache',  
     113      'params' => array ( 
     114        'automaticCleaningFactor' => 0, 
     115        'cacheDir' => sfConfig::get('sf_cache_dir'), 
     116        'lifeTime' => 86400 /* 24 hours */ 
     117      ) 
     118    )); 
     119     
     120    $cache = new $cacheConfig['class'](); 
     121    $cache->initialize(isset($cacheConfig['params']) ? $cacheConfig['params'] : array()); 
     122    return $cache; 
     123  } 
     124  /** 
     125   * Save the UJS to the cache, so that it can be included in an external file. 
     126   * 
     127   * @return boolean true if no problem 
     128   */ 
     129  public function saveToCache() 
     130  { 
     131     
     132    $this->key = $key = md5($this->ujs); 
     133    $cache = self::initCache(); 
     134     
     135    /** 
     136     * The time the cache is considered "new", so that it doesn't have to be reset. 
     137     *  
     138     * The sfCache class doesn't have a method to update the last modified time. 
     139     * Because of that, the cache has to be reset to update the last modified time so that it will still be valid. 
     140     * Resetting the cache all the time is overkill, though, so before setting the cache, 
     141     * the last modified time is checked against $resetTime, and if it is new enough, it won't be reset.  
     142     */ 
     143    $resetTime = sfConfig::get('app_UJSPlugin_cache', array('resetTime' => 43200 /*12 hours*/ )); 
     144    $resetTime = $resetTime['resetTime']; 
     145 
     146    // If the cache is less than $resetTime old, we don't have to reset it. 
     147    if(($cache->lastModified($key, 'symfony/view/UJS') + $resetTime) >= time()) 
     148    {<