Jump to content

Simple, Clear Notes and Method to Use Admin Type Field Inputs on Frontend via API


Recommended Posts

Dear Ryan,

I think that the way you've created the interface to the more exotic field types in the Admin back end is really great.

I'd like to be able to use any or all of those fields on the front end, via the API, more easily, based on a clear and simple set of notes and possible division of .js and .css files per field.

For example, to get the calendar popup working in edit mode, in a front end app, I had to include these files in the <head> section of my pages:

<link type='text/css' href='/site/templates-admin/styles/JqueryUI/JqueryUI.css' rel='stylesheet' />
<link type='text/css' href='/wire/modules/Inputfield/InputfieldDatetime/InputfieldDatetime.css?v=103' rel='stylesheet' />

<script type='text/javascript' src='/wire/modules/Jquery/JqueryCore/JqueryCore.js?v=183'></script>
<script type='text/javascript' src='/wire/modules/Jquery/JqueryUI/JqueryUI.js?v=192'></script>
<script type='text/javascript' src='/wire/modules/Jquery/JqueryWireTabs/JqueryWireTabs.js?v=103'></script>
<script type='text/javascript' src='/wire/modules/Inputfield/InputfieldDatetime/InputfieldDatetime.js?v=103'></script>
<script type='text/javascript' src='/wire/modules/Inputfield/InputfieldDatetime/jquery-ui-timepicker-addon.js'></script>

To get the multi-column checkboxes working in edit mode, I had to include this <div> in my edit form:

<ul class='Inputfields'>
... input field here ...
</ul>

and then I copied a variety of CSS classes from your core code into my main css file.

I'd like to be able to use the image upload field with the progress bar, and many of the other specialized fields that you've created, that require special javascript or css to run properly.

My suggestion is to create js and css files per field -- or field family, that can be easily included, without extra weight from other items, with notes on each field, e.g.

- for xyz field, include these .js and .css files, and add this xyz html to your edit template (if necessary)

This would allow developers to *easily* use the full power of the admin fields in front-end edits, which would be a truly glorious thing. :-)

Thanks!

Peter

  • Like 2
Link to comment
Share on other sites

Greetings,

This is a terrific topic! I have been increasingly using ProcessWire to build front-end admin interfaces.

As Peter says, full UI capabilities here would be "glorious"!

I'd be very interested in pursuing partnerships with anyone who wants to explore this, as I think it is a core area for ProcessWire.

In addition to what Peter says above, I'd also want to look at ways to have back-end validation capabilities in front-end forms.

Thanks,

Matthew

EDIT: corrected Peter. Thanks Manfred! My apologies to Peter for typing before coffee.

Link to comment
Share on other sites


//You create a template in which we poke exactly the fields that interest us.

//Name it "form_callback"

//In theory, we can not even create a page for a form template

//(or do it on the fly using the class NullPage).

//But it is better to create, it will allow us to use the download file.

//Further, on the page where the form should be,

//we create a handler at the top, and print out the form below based on the handler.

$pageForm = $page->child('template=form_callback, include=all'); //get page with template

$templateMessage = $templates->get('message'); //template for conservation requests

//superstructure

$fieldsSkip = array();

$fieldsRequired = array('phone');

$fieldsRows = array('body' => 6);

//Create Form

$form = $modules->get("InputfieldForm");

$form->method = 'post';

$form->action = './';

//Get field from form page

$inputfields = $pageForm->getInputfields();

//add field to form

foreach($inputfields as $inputfield) {

if(in_array($inputfield->name, $fieldsSkip)) continue;

if(in_array($inputfield->name, $fieldsRequired)) $inputfield->required = true;

if(array_key_exists($inputfield->name, $fieldsRows)) $inputfield->rows = $fieldsRows[$inputfield->name];

$form->add($inputfield);

}

//add custom field "submit button and confirm read rules

$checkbox = $modules->get("InputfieldCheckbox");

$checkbox->name = "checkbox";

$checkbox->label = 'I have read the terms and conditions';

$checkbox->skipLabel = 2; // 2 dont output label in name

$checkbox->required = 1;

$form->add($checkbox); //add to form

$submit = $modules->get("InputfieldSubmit");

$submit->name = "submit";

$submit->label = 'Submit';

$submit->value = 1;

$checkbox->required = 1;

$form->add($submit);

//Check the data post

if($this->input->post->submit) {

$form->processInput($this->input->post); //Check data

if(count($form->getErrors())) { //Get new error via validation

ob_start();

echo "<xmp>";

foreach($form as $field) {

if(count($field->getErrors())) {

$name = $field->name;

$errors = $field->getErrors(true); //true - Clean error stack

$error = $errors[0];

echo "$name -> $error\n"; //output fieldname and error message

}

}

echo "</xmp>";

$errorsAsForm = ob_get_contents();

ob_end_clean();

} else {

$pageForm->setOutputFormatting(false); //necessarily have to create page

$pageForm->set('name', date('Y-m-d_H-i-s', time())); //set new name url

$pageForm->set('template', $templateMessage); //set need template

foreach($form as $field) {

$pageForm->set($field->name, $field->value); //set data

}

$pageForm->removeStatus(Page::statusHidden); //clean old status

$pageNew = $pages->clone($pageForm, $page); //Create message page and defined this

$pageForm->setOutputFormatting(true);

}

}

//The next steps depend on you

//You can display the form in a standard way,

//though if it is filled with errors entered data will

//not be lost and errors prompt standard way

//in precisely what fields they were admitted.

$form->render()

//But personally, I am! I love to display the form with your layout, it helps to do ever//ything as I want it, or how it has implemented a front-end


//just example via my project with output image and code for ajax image loaded

<form method="post" action="<?=$page->url?>" enctype="multipart/form-data">

<? foreach ($form as $inputfield) {

$label = $inputfield->label;

$desc = $inputfield->description;

$name = $inputfield->name;

$required = $inputfield->required ? ' required':'';

?>

<?if($inputfield == 'InputfieldTinyMCE'){?>

<label class="text">

<span class="desc">

<?if($inputfield->skipLabel != 2){?>

<b><?=$label?></b>

<?if($desc){?><i><?=$desc?></i><?}?>

<?}?>

</span><span class="text">

<textarea name="<?=$name?>" rows="<?=$inputfield->rows?>"<?=$required?>></textarea>

</span>

</label>

<?}elseif($inputfield == 'InputfieldSubmit'){?>

<label class="submit">

<span class="desc"></span><span class="text">

<button class="button" name="<?=$name?>" type="submit" value="1"<?=$required?>><?=$label?></button>

</span>

</label>

<?}elseif($inputfield == 'InputfieldCheckbox'){?>

<label class="checkbox">

<span class="desc"></span><span class="text">

<input name="<?=$name?>" type="checkbox" value="1"<?=$required?>> Подтверждаю, что согласна с <a href="">условиями конкурса</a> и мне больше 18 лет

</span>

</label>

<?}elseif($inputfield == 'InputfieldImage' || $inputfield == 'InputfieldImagePony'){?>

<label class="files">

<span>

<span class="desc">

<b><?=$label?></b>

</span><span class="text">

<div class="input">

<div class="button">

Загрузить фото<input name="<?=$name?>[]" type="file" multiple="multiple" accept="image/*"<?=$required?>>

</div>

<?if($desc){?><em><?=$desc?></em><?}?>

</div>

<div class="list"><?

foreach ($pageForm->photos as $key => $value) {

if($value) {

$photo = $pageForm->photos->get($key);

?>

<div class="item" data-filename="<?=$photo->name?>">

<div class="del"></div>

<img src="<?=$photo->size(90, 90)->url?>" alt="">

</div>

<?

}

}

?></div>

</span>

</span>

</label>

<?}else{?>

<label class="text">

<span class="desc">

<?if($inputfield->skipLabel != 2){?>

<b><?=$label?></b>

<?if($desc){?><i><?=$desc?></i><?}?>

<?}?>

</span><span class="text">

<input name="<?=$name?>" type="<?=$inputfield->type?>"<?=$required?>>

</span>

</label>

<?}?>

<?}?>

<?

$tokenName = wire('session')->CSRF->getTokenName();

$tokenValue = wire('session')->CSRF->getTokenValue();

$tokenField = "<input type='hidden' id='_post_token' name='$tokenName' value='$tokenValue'>";

?>

<input type="hidden" id="_post_token" name="<?=$tokenName?>" value="<?=$tokenValue?>">


if($config->ajax && isset($_SERVER['HTTP_X_FIELDNAME'])) {

$oid = ob_start();

$form->processInput($this->input->post);

$ajaxResponse = ob_get_contents();

ob_end_clean();

$ajaxResponse = json_decode($ajaxResponse, true);

$ajaxResponse = $ajaxResponse[0];

foreach($form as $field) {

if($field->name == 'photos') {

if($ajaxResponse['error'] == null){

$photo = $field->value->last();

$thumb = $photo->size(90, 90);

$ajaxResponse['markup'] = '<div class="item" data-filename="'.$photo->name.'"><div class="del"></div><img src="'.$thumb->url.'" alt=""></div>';

$files[$photo->name] = true;

$session->reg_files = $files;

}

$ajaxResponse['errors'] = $form->getErrors(true);

echo json_encode($ajaxResponse);

}

}

exit();

}


$('form:eq(0)').each(function(){

var form = $(this)

var url = form.attr('action')

var token = form.find('#_post_token')

var tokenName = token.attr('name')

var tokenValue = token.val()

var filesUpload = form.find("input[type=file]").get(0)

var fieldName = filesUpload.name.slice(0,-2)

var fileList = $(filesUpload).parents('label').find('.list:eq(0)')

if(fileList.find('.item').length)

$(filesUpload).removeAttr('required');

function uploadFile(file) {

var progressBar = $('<div class="progressBar"><div class="over">' + file.name + ' - ' + parseInt(file.size / 1024, 10) + ' kb</div><div class="bar" style="width:0%"></div></div>')

var xhr = new XMLHttpRequest()

xhr.upload.addEventListener("progress", function (e) {

if(e.lengthComputable) {

var completion = (e.loaded / e.total) * 100

progressBar.find('.bar').width(completion + "%")

if(completion > 4) {

progressBar.find('.over').html("Загрузка - " + parseInt(completion) + "%")

}

}

}, false)

xhr.addEventListener("load", function() {

var response = $.parseJSON(xhr.responseText)

if(response.error) {

} else {

var markup = $(response.markup)

fileList.append(markup)

fileList.append(' ')

if(fileList.find('.item').length)

$(filesUpload).removeAttr('required');

}

progressBar.remove()

}, false)

// Here we go

xhr.open("POST", url, true)

xhr.setRequestHeader("X-FILENAME", file.name)

xhr.setRequestHeader("X-FIELDNAME", fieldName)

xhr.setRequestHeader("X-" + tokenName, tokenValue)

xhr.setRequestHeader("X-REQUESTED-WITH", 'XMLHttpRequest')

xhr.setRequestHeader("Content-Type", "application/octet-stream")

xhr.send(file);

fileList.append(progressBar)

}

function traverseFiles(files) {

for(var i=0, l=files.length; i<l; i++) {

var extension = files.name.split('.').pop().toLowerCase()

uploadFile(files)

}

}

filesUpload.addEventListener("change", function(e) {

traverseFiles(this.files)

e.preventDefault()

e.stopPropagation()

this.value = ''

}, false)

})

Link to comment
Share on other sites

Dear Matthew,

Hey, those Biblical names are easy to mix up: Peter, David, Matthew, Lazarus... :-)

Fancybox Lightboxes on Front end Images:

To all, here's another example:

I just parsed through an admin page, to determine what's needed on the front end to use the Fancybox lightboxes on an href to an image, and came up with this:

<link type='text/css' href='/wire/modules/Jquery/JqueryFancybox/JqueryFancybox.css?v=126' rel='stylesheet' />

<script type='text/javascript' src='/wire/modules/Jquery/JqueryCore/JqueryCore.js?v=183'></script>
<script type='text/javascript' src='/wire/modules/Jquery/JqueryFancybox/JqueryFancybox.js?v=126'></script>
<script type='text/javascript' src='/wire/modules/Inputfield/InputfieldImage/InputfieldImage.js?v=100'></script>

<!--
For the Fancybox to work, the hrefs that link to images need this class:
<a class='InputfieldFileLink' href='xyz.jpg'>
-->

In the Significato Journal, we use a lot of images in the articles, and I'd like to start using popups to larger versions.

PW has that very fine function, when you add an image to a page (in TinyMCE), to automatically scale a smaller image down, and it has a check box if you want to link to the larger image. I like that a lot.

But... by default, it doesn't have a checkbox for target blank, and it doesn't have a dialogue box to use the Fancybox popup. (Unless I missed something.)

So, on this article for example:

http://significatojournal.com/help-the-world/freedom-human-rights/help-to-end-the-unbearable-evil-of-modern-slavery/

I created a sidebar with images, linking to larger versions.

Once I added the above Fancybox css and js files AND manually added the string

class='InputfieldFileLink'

to the first image in the sidebar, (via the HTML code button in the body text editor), the first image used the Fancybox popup!

Zowie! I love it.

(I haven't edited the other images yet.)

Yes: I read the comments on another post about not using the default JQuery files, so I understand that risk. Maybe I'll copy them to my site dir.

My questions now are:

a) WISHLIST: it would be really great to add a dialogue box on the image insert, to use the Fancybox module, and

b) does anyone have any clever code ideas to parse through the body text and edit the <a hrefs> that have images with the above class string?

I don't want to add that class to every href in the body text. I suppose I could use a preg_match to grab every <a ...> and then check for a '.jpg', '.png', '.gif', and then add the class to that string.

Just kicking ideas around.

Thanks!

Peter

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...