I am developing Custom Component for Joomla.
I did well in validating field by adding custom rule. But if entered value does not pass through my validation, it gives error as "Invalid Field: My Field Name"
I want to replace this with my own message.
I know I can use "JText::_('LANGUAGE_STRING'). But I'm not sure where do I need to add it.
I have custom rule called "validemails" which returns false in client side as well as server side validation.
My Client side Validation is: (components/com_helpdesk/models/forms/create.js)
jQuery(document).ready(function () {
document.formvalidator.setHandler('validemail', function (value) {
var emails = [value];
if (value.indexOf(';') !== -1) {
emails = value.split(';');
}
else if(value.indexOf(',') !== -1) {
emails = value.split(',');
}
regex = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
var result = false;
emails.each(function (value) {
result = regex.test(jQuery.trim(value));
if (result === false) {
return false;
}
});
return result;
});
});
My Server Side Validation is: (components/com_helpdesk/models/rules/validemail.php)
use Joomla\Registry\Registry;
JFormHelper::loadRuleClass('email');
class JFormRuleValidemail extends JFormRuleEmail {
public function test(SimpleXMLElement $element, $value, $group = null, Registry $input = null, JForm $form = null) {
$emails = array($value);
if (strpos($value, ';') !== false) {
$emails = explode(';', $value);
}
else if (strpos($value, ',') !== false) {
$emails = explode(',', $value);
}
foreach ($emails as $email) {
if (!parent::test($element, trim($email))) {
return false;
continue;
}
}
return true;
}
}
Please note that I'm developing Front-end view of Component not back-end.
Well fortunately, I got my server side validation working by this way:
use Joomla\Registry\Registry;
JFormHelper::loadRuleClass('email');
class JFormRuleValidemail extends JFormRuleEmail {
public function test(SimpleXMLElement $element, $value, $group = null, Registry $input = null, JForm $form = null) {
$emails = array($value);
if (strpos($value, ';') !== false) {
$emails = explode(';', $value);
}
else if (strpos($value, ',') !== false) {
$emails = explode(',', $value);
}
foreach ($emails as $email) {
if (!parent::test($element, trim($email))) {
***$element->addAttribute('message', JText::_('COM_HELPDESK_ERROR_EMAIL').' '.$value);***
return false;
continue;
}
}
return true;
}
}
I got the solution. May be it will be useful for other googlers. Below is a code snippet for client side validation. Put below code in your custom JS:
jQuery('.validate').click(function (e) {
var fields, invalid = [], valid = true, label, error, i, l;
fields = jQuery('form.form-validate').find('input, textarea, select');
if (!document.formvalidator.isValid(jQuery('form'))) {
for (i = 0, l = fields.length; i < l; i++) {
if (document.formvalidator.validate(fields[i]) === false) {
valid = false;
invalid.push(fields[i]);
}
}
// Run custom form validators if present
jQuery.each(document.formvalidator.custom, function (key, validator) {
if (validator.exec() !== true) {
valid = false;
}
});
if (!valid && invalid.length > 0) {
error = {"error": []};
for (i = invalid.length - 1; i >= 0; i--) {
label = jQuery.trim(jQuery(invalid[i]).data("label").text().replace("*", "").toString());
if (label) {
if(label === 'Subject') {
error.error.push('Please Enter Subject');
}
if(label === 'Description') {
error.error.push('Please Enter Description');
}
if(label === 'Priority') {
error.error.push('Please Select Priority');
}
if(label === 'Email CCs') {
error.error.push('Please Enter proper Emails in CC section');
}
if(label === 'Email BCCs') {
error.error.push('Please Enter proper Emails in BCC section');
}
}
}
}
Joomla.renderMessages(error);
}
e.preventDefault();
});
Related
So I get this error when I'm trying to use the voyager themes, I want to use the voyager's theme since the page is on the admin side so I want to make it uniform.
I realized that I also need to to extend the views so I create this controller
<?php
namespace App\Http\Controllers\Admin;
use App\Models\Toko;
use App\Models\SubOrder;
use Illuminate\Http\Request;
use TCG\Voyager\Facades\Voyager;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use RealRashid\SweetAlert\Facades\Alert;
use Illuminate\Database\Eloquent\SoftDeletes;
use TCG\Voyager\Database\Schema\SchemaManager;
use TCG\Voyager\Http\Controllers\VoyagerBaseController;
class OrderController extends VoyagerBaseController
{
//***************************************
// ____
// | _ \
// | |_) |
// | _ <
// | |_) |
// |____/
//
// Browse our Data Type (B)READ
//
//****************************************
public function index(Request $request)
{
// GET THE SLUG, ex. 'posts', 'pages', etc.
$slug = $this->getSlug($request);
// GET THE DataType based on the slug
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();
// Check permission
$this->authorize('browse', app($dataType->model_name));
$getter = $dataType->server_side ? 'paginate' : 'get';
$search = (object) ['value' => $request->get('s'), 'key' => $request->get('key'), 'filter' => $request->get('filter')];
$searchNames = [];
if ($dataType->server_side) {
$searchable = SchemaManager::describeTable(app($dataType->model_name)->getTable())->pluck('name')->toArray();
$dataRow = Voyager::model('DataRow')->whereDataTypeId($dataType->id)->get();
foreach ($searchable as $key => $value) {
$field = $dataRow->where('field', $value)->first();
$displayName = ucwords(str_replace('_', ' ', $value));
if ($field !== null) {
$displayName = $field->getTranslatedAttribute('display_name');
}
$searchNames[$value] = $displayName;
}
}
$orderBy = $request->get('order_by', $dataType->order_column);
$sortOrder = $request->get('sort_order', $dataType->order_direction);
$usesSoftDeletes = false;
$showSoftDeleted = false;
// Next Get or Paginate the actual content from the MODEL that corresponds to the slug DataType
if (strlen($dataType->model_name) != 0) {
$model = app($dataType->model_name);
if ($dataType->scope && $dataType->scope != '' && method_exists($model, 'scope'.ucfirst($dataType->scope))) {
$query = $model->{$dataType->scope}();
} else {
$query = $model::select('*');
}
// Query menampilkan hanya toko pedagang
if(auth()->user()->hasRole('pedagang')) {
$query->where('user_id', auth()->id());
}
// Use withTrashed() if model uses SoftDeletes and if toggle is selected
if ($model && in_array(SoftDeletes::class, class_uses_recursive($model)) && Auth::user()->can('delete', app($dataType->model_name))) {
$usesSoftDeletes = true;
if ($request->get('showSoftDeleted')) {
$showSoftDeleted = true;
$query = $query->withTrashed();
}
}
// If a column has a relationship associated with it, we do not want to show that field
$this->removeRelationshipField($dataType, 'browse');
if ($search->value != '' && $search->key && $search->filter) {
$search_filter = ($search->filter == 'equals') ? '=' : 'LIKE';
$search_value = ($search->filter == 'equals') ? $search->value : '%'.$search->value.'%';
$query->where($search->key, $search_filter, $search_value);
}
if ($orderBy && in_array($orderBy, $dataType->fields())) {
$querySortOrder = (!empty($sortOrder)) ? $sortOrder : 'desc';
$dataTypeContent = call_user_func([
$query->orderBy($orderBy, $querySortOrder),
$getter,
]);
} elseif ($model->timestamps) {
$dataTypeContent = call_user_func([$query->latest($model::CREATED_AT), $getter]);
} else {
$dataTypeContent = call_user_func([$query->orderBy($model->getKeyName(), 'DESC'), $getter]);
}
// Replace relationships' keys for labels and create READ links if a slug is provided.
$dataTypeContent = $this->resolveRelations($dataTypeContent, $dataType);
} else {
// If Model doesn't exist, get data from table name
$dataTypeContent = call_user_func([DB::table($dataType->name), $getter]);
$model = false;
}
// Check if BREAD is Translatable
$isModelTranslatable = is_bread_translatable($model);
// Eagerload Relations
$this->eagerLoadRelations($dataTypeContent, $dataType, 'browse', $isModelTranslatable);
// Check if server side pagination is enabled
$isServerSide = isset($dataType->server_side) && $dataType->server_side;
// Check if a default search key is set
$defaultSearchKey = $dataType->default_search_key ?? null;
// Actions
$actions = [];
if (!empty($dataTypeContent->first())) {
foreach (Voyager::actions() as $action) {
$action = new $action($dataType, $dataTypeContent->first());
if ($action->shouldActionDisplayOnDataType()) {
$actions[] = $action;
}
}
}
// Define showCheckboxColumn
$showCheckboxColumn = false;
if (Auth::user()->can('delete', app($dataType->model_name))) {
$showCheckboxColumn = true;
} else {
foreach ($actions as $action) {
if (method_exists($action, 'massAction')) {
$showCheckboxColumn = true;
}
}
}
// Define orderColumn
$orderColumn = [];
if ($orderBy) {
$index = $dataType->browseRows->where('field', $orderBy)->keys()->first() + ($showCheckboxColumn ? 1 : 0);
$orderColumn = [[$index, $sortOrder ?? 'desc']];
}
$view = 'voyager::bread.browse';
if (view()->exists("voyager::$slug.browse")) {
$view = "voyager::$slug.browse";
}
// $order = SubOrder::class;
// $items = $order->items;
$tokoId = Toko::select('id')->firstWhere('user_id', auth()->id())->id;
// $orders = SubOrder::where('toko_id', $tokoId)->orderBy('created_at', 'desc')->get();
$orders = SubOrder::with('items')->where('toko_id', $tokoId)->orderBy('created_at', 'desc')->get();
return view('sellers.order.index', compact(
// 'items',
'orders',
'actions',
'dataType',
'dataTypeContent',
'isModelTranslatable',
'search',
'orderBy',
'orderColumn',
'sortOrder',
'searchNames',
'isServerSide',
'defaultSearchKey',
'usesSoftDeletes',
'showSoftDeleted',
'showCheckboxColumn'
));
}
// public function show(SubOrder $order)
// {
// $items = $order->items;
// return view('sellers.order.show', compact('items'));
// }
public function markTolak(SubOrder $suborder)
{
$suborder->status = 'gagal';
$suborder->save();
Alert::info('Order di Proses!', 'Order ditandai proses!');
return redirect('/seller/orders')->withMessage('Order ditandai proses');
}
public function markProses(SubOrder $suborder)
{
$suborder->status = 'proses';
$suborder->save();
Alert::info('Order di Proses!', 'Order ditandai proses!');
return redirect('/seller/orders')->withMessage('Order ditandai proses');
}
public function markDelivered(SubOrder $suborder)
{
$suborder->status = 'selesai';
$suborder->save();
// Check all sub order complete
$pendingSubOrders = $suborder->order->subOrders()->where('status','!=', 'selesai')->count();
if($pendingSubOrders == 0) {
$suborder->order()->update(['status'=>'selesai']);
}
Alert::success('Order Selesai!', 'Order ditandai selesai!');
return redirect('/seller/orders')->withMessage('Order ditandai selesai');
}
}
it shows that the error is from the line 42 where it checks the permission and couldn't find the "model_name". please help
Or maybe if there's another way to use the template?
I want to validate login form with ajax. I am using form valiation with a callback function that check username in database. When I am using callback with set_message, form validation errors are not working, only that callback error message is shown. If username is empty then form validation error like "Username is required" should be shown first and then if user enter wrong username then callback function error like "Username is not correct" should be shown
Following are the functions in my controller
public function validate_form()
{
$data = array('success' => false, 'messages' => array());
$this->form_validation->set_rules('username', 'Username', 'required|trim|xss_clean|callback_username_check');
$this->form_validation->set_rules('password', 'Password', 'required|trim|xss_clean|callback_password_check');
$this->form_validation->set_error_delimiters('<p class="text-danger">', '</p>');
if ($this->form_validation->run()) {
$data['success'] = true;
$this->session->set_userdata('admin_username', $this->input->post('username'));
} else {
foreach ($_POST as $key => $value) {
$data['messages'][$key] = form_error($key);
}
}
echo json_encode($data);
}
public function username_check()
{
$username = $this->input->post("username");
if ($this->admin_model->usernameDB()) {
return true;
} else {
$this->form_validation->set_message('username_check', 'The {field} is not correct');
return false;
}
}
public function password_check()
{
$password = $this->input->post("password");
if ($this->admin_model->passwordDB($password)) {
return true;
} else {
$this->form_validation->set_message('password_check', 'The {field} is not correct');
return false;
}
}
Following are the function in my model
public function usernameDB() {
$this->db->where('username', $this->input->post('username'));
$query = $this->db->get('adminuser');
if ($query->num_rows() == 1) {
return true;
} else {
return false;
}
}
public function passwordDB() {
$this->db->where('password', md5($this->input->post('password')));
$query = $this->db->get('adminuser');
if ($query->num_rows() == 1) {
return true;
} else {
return false;
}
}
Following is the ajax that i am using
$("#admin_login_form").submit(function(e) {
e.preventDefault();
var me = $(this);
// perform ajax
$.ajax ({
url: "validate_form",
type: "post",
data: me.serialize(),
dataType: "json",
success: function(response) {
if (response.success == true) {
$('.form-group').removeClass('has-error')
.removeClass('has-success');
$('.text-danger').remove();
window.location = "member";
} else {
$.each(response.messages, function(key, value) {
var element = $('#' + key);
element.closest('div.form-group')
.removeClass('has-error')
.addClass(value.length > 0 ? 'has-error' : 'has-success')
.find('.text-danger')
.remove();
element.after(value);
});
}
}
});
});
I want proper validation errors order like if username or password is empty then first their relevant errors should be shown like username or password is required and then wrong or correct username or password errors should be shown.
You can try below. You can use single callback function to check whether user is exists or not.
First, remove the callback functions public function username_check() and public function password_check() from your controller and replace with the updated functions below.
In addition to this created new model function login inside admin_model which will check whether user is exists or not. Also you can delete both usernameDB and passwordDB from your admin_model.
Controller function:
public function validate_form()
{
$data = array('success' => false, 'messages' => array());
$this->form_validation->set_rules('username', 'Username', 'required|trim|xss_clean');
$this->form_validation->set_rules('password', 'Password', 'required|trim|xss_clean|is_user_exists');
$this->form_validation->set_error_delimiters('<p class="text-danger">', '</p>');
if ($this->form_validation->run()) {
$data['success'] = true;
$this->session->set_userdata('admin_username', $this->input->post('username'));
} else {
foreach ($_POST as $key => $value) {
$data['messages'][$key] = form_error($key);
}
}
echo json_encode($data);
}
public function is_user_exists()
{
if ($this->admin_model->login($this->input->post('username', TRUE), $this->input->post('password', TRUE))) {
return true;
} else {
$this->form_validation->set_message('is_user_exists', 'Login failed. Username or password is incorrect');
return false;
}
}
Model function:
public function login($username, $password)
{
$this->db->where('username', $username);
$this->db->where('password', md5($password));
$query = $this->db->get('adminuser');
if ($query->num_rows() > 0) {
return true;
} else {
return false;
}
}
Note: Using md5 for encrypt password is not good. See Alex's comment for more details.
I want to have a comments box in my website using codeigniter with Ajax. I want if the comment success show new comment. Else show validation error. How to do it?
This is my controller form validation
if ($this->form_validation->run() == TRUE) {
$this->load->model('comment_model');
$this->load->model('user_model');
if($this->comment_model->insert_comment())
{
$data['user_comment']= $this->user_model->get_user_session($this->session->userdata('user_id'));
$data['new_comment']= $this->comment_model->get_one_comment();
$this->load->view('user/insert_comment',$data);
}
} else {
echo validation_errors();
}
This is my ajax success function.
success: function (data) {
if (data)// this is what is need. How to make a if condition
{
$('ol#update').prepend(data);
$('ol#update li:first').slideDown('slow');
}
else
{
$('#myerror1').html(data);
}
}
Return answer from controller as Json and parse it in success function.
if ($this->form_validation->run() == TRUE) {
$this->load->model('comment_model');
$this->load->model('user_model');
if($this->comment_model->insert_comment()) {
$data['user_comment']=$this->user_model->get_user_session($this->session->userdata('user_id'));
$data['new_comment']= $this->comment_model->get_one_comment();
// third argument means, return template as string instead of echo.
$data = $this->load->view('user/insert_comment',$data, TRUE);
$array = array();
$array['success'] = true;
$array['data'] = $data;
} else {
$array = array();
$array['success'] = false;
$array['data'] = validation_errors();
}
echo json_encode($array);
}
And in success function:
success: function (data) {
var jsonData = JSON.parse(data);
if (jsonData.success == true) {
$('ol#update').prepend(jsonData.data);
$('ol#update li:first').slideDown('slow');
} else {
$('#myerror1').html(jsonData.data);
}
}
I have just created a library class in laravel.
class Message {
public static $data = array();
public function __construct() {
// If session has flash data then set it to the data property
if (Session::has('_messages')) {
self::$data = Session::flash('_messages');
}
}
public static function set($type, $message, $flash = false) {
$data = array();
// Set the message properties to array
$data['type'] = $type;
$data['message'] = $message;
// If the message is a flash message
if ($flash == true) {
Session::flash('_messages', $data);
} else {
self::$data = $data;
}
}
public static function get() {
// If the data property is set
if (count(self::$data)) {
$data = self::$data;
// Get the correct view for the message type
if ($data['type'] == 'success') {
$view = 'success';
} elseif ($data['type'] == 'info') {
$view = 'info';
} elseif ($data['type'] == 'warning') {
$view = 'warning';
} elseif ($data['type'] == 'danger') {
$view = 'danger';
} else {
// Default view
$view = 'info';
}
// Return the view
$content['body'] = $data['message'];
return View::make("alerts.{$view}", $content);
}
}
}
I can use this class in my views calling Message::get(). In the controllers, I can set the message as Message::set('info', 'success message here.'); and it works perfectly fine.
However, I can not use this class for flash messages redirects using Message::set('info', 'success message here.', true). Any idea, whats wrong in this code?
First problem is the constructor function is not called when using the above get and set methods, with minor modification the code is now working. :)
class Message {
public static $data = array();
public static function set($type, $message, $flash = false) {
$data = array();
// Set the message properties to array
$data['type'] = $type;
$data['message'] = $message;
// If the message is a flash message
if ($flash == true) {
Session::flash('_messages', $data);
} else {
self::$data = $data;
}
}
public static function get() {
// Check the session if message is available in session
if (Session::has('_messages')) {
self::$data = Session::get('_messages');
}
// If the data property is set
if (count(self::$data)) {
$data = self::$data;
// Get the correct view for the message type
if ($data['type'] == 'success') {
$view = 'success';
} elseif ($data['type'] == 'info') {
$view = 'info';
} elseif ($data['type'] == 'warning') {
$view = 'warning';
} elseif ($data['type'] == 'danger') {
$view = 'danger';
} else {
// Default view
$view = 'info';
}
// Return the view
$content['body'] = $data['message'];
return View::make("alerts.{$view}", $content);
}
}
}
I have a webform and mymodule which alters it. The webform has a field stelle which gets populated based on the url query. For instance, if ?stelle=10 the field gets populated by the title of node with nid 10. If the query ?stelle is non-existant or followed by a nid which does not exist (is not of a certain content type) or does not contain a certain string the form will be redirecting to mynode?stelle=initiativ. The form has 2 fields to upload files via ajax, works good so far. Here is my code:
<?php
/**
* Altering the form! this will add class to the file upload/ remove buttons
*/
function mymodule_form_alter(&$form, &$form_state, $form_id) {
$conf = mymodule_defaults();
if ($form_id == 'webform_client_form_' . $conf['nid']) {
if (isset($form['submitted']['field1'])) {
$form['submitted']['field1']['#process'] = array('mymodule_my_file_element_process');
}
if (isset($form['submitted']['field2'])) {
$form['submitted']['field2']['#process'] = array('mymodule_my_file_element_process');
}
$nid = $form['#node']->nid;
$form['actions']['submit']['#ajax'] = array(
'callback' => 'mymodule_webform_js_submit',
'wrapper' => 'webform-client-form-' . $nid,
'method' => 'replace',
'effect' => 'fade',
);
$redirect_form = false;
$maintenance = false;
if (isset($form['submitted']['stelle']['#default_value']) && $form['submitted']['stelle']['#default_value'] !== '') {
$hide_components = array(
'einleitung_standard',
'einleitung_initiativ',
);
$unhide_components = array();
if ($form['submitted']['stelle']['#default_value'] == '') {
$redirect_form = true;
}
elseif (is_numeric($form['submitted']['stelle']['#default_value'])) {
$nid = $form['submitted']['stelle']['#default_value'];
$node = node_load($nid);
if ($node === false || (isset($node->type) && $node->type !== 'job')) {
$redirect_form = true;
}
else {
$type = $node->type;
if ($type == 'job') {
$form['submitted']['stelle']['#default_value'] = $node->title;
$form['submitted']['stelle']['#attributes']['disabled'] = 'disabled';
$form['submitted']['related']['#value'] = $nid;
$unhide_components = array(
'einleitung_standard'
);
}
}
}
elseif ($form['submitted']['stelle']['#default_value'] == 'initiativ') {
// unset($form['submitted']['stelle']);
$form['submitted']['related']['#value'] = 'initiativ';
$unhide_components = array(
'einleitung_initiativ'
);
}
}
else {
// $redirect_form = true;
// this causes an error
}
This is the weird part:
$redirect_form = false;
$maintenance = false;
if (isset($form['submitted']['stelle']['#default_value']) && $form['submitted']['stelle']['#default_value'] !== '') {
...
else {
// $redirect_form = true;
// this causes an error
}
When I active the line to redirect the form when the if condition is false, the button to upload a file via ajax throws an error alert on click (see bottom for error). To me, this looks like the form alter hook is being called again when the file upload button is clicked without having my field stelle available - is that right? How to fix this?
And now the rest of the module, basically just alterings:
else {
// $redirect_form = true;
// this causes an error
}
foreach ($unhide_components as $key => $component) {
if (is_array($component)) {
foreach ($component as $_key => $_component) {
$index = array_search($_component, $hide_components[$key]);
if ($index !== false) {
unset($hide_components[$key][$index]);
}
}
}
else {
$index = array_search($component, $hide_components);
if ($index !== false) {
unset($hide_components[$index]);
}
}
}
// hide
foreach ($hide_components as $k=>$hc1){
if (is_array($hc1)) {
foreach ($hc1 as $hc2) unset($form['submitted'][$k][$hc2]);
} else {
unset($form['submitted'][$hc1]);
}
}
if ($redirect_form) drupal_goto('node/'.$conf['nid'], array('query'=>array('stelle'=>'initiativ')), 301);
}
}
function mymodule_my_file_element_process($element, &$form_state, $form) {
$element = file_managed_file_process($element, $form_state, $form);
$element['upload_button']['#attributes'] = array('class' => array('button'));
$prefix = '<label class="browse-slave">';
$prefix .= '<span class="button">' . t('Choose a file') . '</span>';
$element['upload']['#prefix'] = $prefix;
$element['upload_button']['#prefix'] = '</label>';
$element['remove_button']['#attributes'] = array('class' => array('button'));
$element['remove_button']['#prefix'] = '</label>';
return $element;
}
function mymodule_webform_js_submit($form, $form_state) {
// define the $sid variable (submission id from webform)
$sid = $form_state['values']['details']['sid'];
// if we have a sid then we know the form was properly submitted, otherwise, we'll just return the existing $form array
if ($sid) {
// first we have to load up the webform node object
$node = node_load($form_state['values']['details']['nid']);
// create an array up with the confirmation message, retreived from the webform node
$confirmation = array(
'#type' => 'markup',
'#markup' => check_markup($node->webform['confirmation'], $node->webform['confirmation_format'], '', TRUE),
);
// return the confirmation message
return $confirmation;
}
else {
// return the form
return $form;
}
}
The AJAX error is something like described here. Changing server/php settings didnt help it.
Thanks!
The form builder (and any hook alters) will be run when a form is validated, which happens on #ajax actions.
I like to throw static custom data in $form['#someProperty'] so that it's available in the build, validate, and submit functions. Something like this should help you:
function mymodule_form_alter(&$form, &$form_state, $form_id) {
// ...
if (isset($_GET['stelle'])) {
$form['#stelle'] = $_GET['stelle']; // This will always be there.
}
// ...
}
Another option would be to throw the $node that you load in the form, like $form['#stelle_node'] = node_load(...) and obviously only do that when the nid is actually available to you, so that you don't overwrite it with empty data when the form builder runs again in the future.
When i was working with ajax in drupal 6 the hash symbol in url or request caused an error everytime..... so i replaced url with this
data.url.replace(/%2523/, '%23');