Jestem pewien, że istnieje wiele sposobów, aby wyciągnąć ten mecz, ale tutaj jest moje rozwiązanie. Używam mechanizmu szablonów Smarty, ale ta technika powinna również działać z HTML-em wanilii.
Po pierwsze, oto przykład jakiegoś HTML przechowywanych w moim pliku szablonu o nazwie "dog_fleas.tpl":
<script type="text/javascript" src="/js/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="/js/admin/mycms.js"></script>
<div>
<div id="flea-blurb" tpl="/templates/dog_fleas.tpl" contenteditable="true">
<h1>My Dog Has Fleas</h1>
<p>This text is editable via the CMS!</p>
</div>
<p>This text is not editable</p>
</div>
javascript (mycms.js) do obsługi edycji inline jest:
$(document).ready(function() {
CKEDITOR.disableAutoInline = true;
$("div[contenteditable='true']").each(function(index) {
var content_id = $(this).attr('id');
var tpl = $(this).attr('tpl');
CKEDITOR.inline(content_id, {
on: {
blur: function(event) {
var data = event.editor.getData();
var request = jQuery.ajax({
url: "/admin/cms-pages/inline-update",
type: "POST",
data: {
content : data,
content_id : content_id,
tpl : tpl
},
dataType: "html"
});
}
}
});
});
});
powyższy kod robi kilka rzeczy:
- konwertuje dowolny znacznik div z contentEditable atrybut = "true" inline-edit zdolny.
- Po edycji treści (w przypadku rozmycia), edytowalny element id, nazwa pliku tpl i edytowana zawartość są wysyłane na serwer za pośrednictwem wywołania ajax.
Atrybut tpl jest niezbędny w mojej sytuacji do zidentyfikowania edytowanego pliku. Identyfikator elementu określa, który element został zmodyfikowany.
Chociaż mój przykład zawiera tylko jeden edytowalny region, ten kod obsługuje wiele edytowalnych regionów w jednym pliku.
Po stronie serwera, oto mój kod PHP. Używam ramy, więc mój $ this -> _ POST() funkcji może wyglądać trochę nietypowe, ale mam nadzieję, że masz pomysł:
// Get the posted parameters
$new_content = $this->_POST('content');
$content_id = $this->_POST('content_id');
$tpl_filename = $this->_POST('tpl');
// Get the contents of the .tpl file to edit
$file_contents = file_get_contents(APPPATH . 'views' . $tpl_filename);
// create revision as a backup in case of emergency
$revised_filename = str_replace('/', '.', $tpl_filename);
$revised_filename = ltrim ($revised_filename, '.');
file_put_contents(APPPATH . 'views/templates/revisions/' . $revised_filename . '.' . time(), $file_contents);
// Prepare to match the DIV tag
// Credit to: http://stackoverflow.com/questions/5355452/using-a-regular-expression-to-match-a-div-block-having-a-specific-id
$re = '% # Match a DIV element having id="content".
<div\b # Start of outer DIV start tag.
[^>]*? # Lazily match up to id attrib.
\bid\s*+=\s*+ # id attribute name and =
([\'"]?+) # $1: Optional quote delimiter.
\b' . $content_id . '\b # specific ID to be matched.
(?(1)\1) # If open quote, match same closing quote
[^>]*+> # remaining outer DIV start tag.
( # $2: DIV contents. (may be called recursively!)
(?: # Non-capture group for DIV contents alternatives.
# DIV contents option 1: All non-DIV, non-comment stuff...
[^<]++ # One or more non-tag, non-comment characters.
# DIV contents option 2: Start of a non-DIV tag...
| < # Match a "<", but only if it
(?! # is not the beginning of either
/?div\b # a DIV start or end tag,
| !-- # or an HTML comment.
) # Ok, that < was not a DIV or comment.
# DIV contents Option 3: an HTML comment.
| <!--.*?--> # A non-SGML compliant HTML comment.
# DIV contents Option 4: a nested DIV element!
| <div\b[^>]*+> # Inner DIV element start tag.
(?2) # Recurse group 2 as a nested subroutine.
</div\s*> # Inner DIV element end tag.
)*+ # Zero or more of these contents alternatives.
) # End 2$: DIV contents.
</div\s*> # Outer DIV end tag.
%isx';
if (preg_match($re, $file_contents, $matches))
{
$content_to_replace = $matches[0];
$replacement_content = $content_to_replace;
// Replace the inner content of $replacement_content with $new_content
$replacement_content = preg_replace('/(<div(?:.*?)>)(?:.*)(<\/div>)/msi',"$1" . $new_content . "$2", $replacement_content);
// Now replace the content_to_replace with $replacement content in the HTML
$new_file_contents = str_replace($content_to_replace, $replacement_content, $file_contents);
// write out the new .tpl file
file_put_contents(APPPATH . 'views' . $tpl_filename, $new_file_contents);
}
Kod PHP powyżej jest w zasadzie ładowania HTML, lokalizowanie div tag z poprawnym id, a następnie zastąpienie zawartości tego znacznika div treścią wysyłaną za pośrednictwem wywołania ajax. Kod HTML jest następnie ponownie zapisywany na serwerze. Załączam także kod do przechowywania wersji zapasowych, na wypadek gdyby coś poszło nie tak.
Zdaję sobie sprawę, że wyrażenia regularne nie zawsze są najlepszym rozwiązaniem. W moim przypadku trudno było używać modelu obiektowego PHP Dom, ponieważ moja treść HTML nie jest poprawna HTML. Możesz spojrzeć na użycie Domowego Modelu Domowego, jeśli twój system jest prostszy niż mój.
Mam nadzieję, że to pomoże!
Dziękujemy! Szukałem, jak wystrzelić żądanie ajax dla tego. Twoje rozwiązanie jest idealne do mojej adopcji. – Dave