L'uso di questo sito
autorizza anche l'uso dei cookie
necessari al suo funzionamento.
(Altre informazioni)

Friday, July 31, 2015

Efficient CKeditor tabbing with bootstrap and jquery

The Problem


Ok, so you are back in web coding and want to add the nifty CKeditor to your site, so some admin will be edit to add, say descriptions or notes in crisp, nicely formatted HTML (or maybe crufty, luridly formatted HTML - it really makes no difference).

More than that, you need to do that in a form, want to keep your elements as textareas, and you need more than one editor - in fact, you want one per language on a multilanguage site. Also you would like to keep not in use editors tucked away from view.

So you gather a tabbing widget, put textareas where they belong, deploy your editors in their place (no, not going into details here, but they will be shown momentarily).

And behold! Everything is painfully slow, even  with a paltry 4 editors on your page (four europeans languages, is that asking too much?). Ouch.

The idea. The recipe

Of course, what's needed is:
  • lazy creation of the editors
This is OK, since most of them are already out of view when the page starts up - that's because we're tabbing, remember?

This also means that the admirably short:

$('textarea').ckeditor()

provided by CKeditor's jquery plugin won't cut it, as it will do everything at once, and your page will pop back up to consciousness only after it's finished - several seconds later.

This is not enough, however. CKeditor's 'classic' view, sitting in its own iframe, is quite hefty in itself - and even with lazy instantiation, mapping the GUI takes forever. So I'll also need:

That's lingo meaning that CKeditor will be attached to an element until it is clicked, when it springs into existence. That turns out to be much lighter.

CKeditor will inline a lot of elements which set the HTML5 attribute contenteditable to true - DIVs, notably .  I am an old timer, however, and I want this to happen in a form's textarea, so I can enjoy the automatic variable population that happens when my little lusers hit the "Submit" button. (Aside: can this also be made to happen with DIVs, I wonder? Comment if you know it.)

Critically, CKeditor allows to do inline on textareas  since V4.2. And this is another reason why the jquery plugin for CKeditor cannot be used - its .ckeditor() method appears to force 'classic' view on textareas (a feature request that appears to be promising on the CK's blog gave me no joy whatsoever).

What else? Oh, right, I'm gonna need

unless, that is, one wants to do the  click-hide-show wiring and dance by hand. (Which I did, on first iteration. Darn me, for not knowing my manuals - but I'm old, did I already mention it? So never mind me). Not to worry, bootstrap (which makes everything oh, so 2.0 not to mention, responsive) has a perfectly fine tabbing widget camped on an appropriatedly marked up UL section. Be sure to read up on it carefully, or you will be liable to miss (as I did) the critical part on javascript plumbing that makes  the tabbing automatic.

And because it's bootstrap, and 2015 to boot,  I'm going to spruce it all up by adding:

to the mix - after all, bootstrap needs jquery, and will everybody wanting to do browser sniffing  on their own please raise their hands? I thought so. Which of course also implies we will want a last ingredient:

anything above IE8 will do, but surely you have that - you are not still supporting IE6 and Netscape 4.7, are you? Or, God forbid, IE7.

And voilà. Sounds easy? It's not.

The reasearch

And so, google and stackoverflow to the rescue, you start looking for the solution's pieces, and put them together , and it takes a day or more. Unless of course you stumbled on this page, where I laid it all down for you, my trusty reader. (It took more than a day, thank you very much - show your gratitude by sending money - lots  of it - in a stamped envelope. Yes, I'm that greedy.)

The execution

Markup: the header



<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title>CKEditor ALF</title>
 <link href="/core/jquery-ui-1.11.4/jquery-ui.min.css" rel="stylesheet" type="text/css">
 <script type="text/javascript" src="/core/jquery/jquery-1.11.1.min.js"></script>
 <script type="text/javascript" src="/core/jquery-ui-1.11.4/jquery-ui.min.js"></script>

 <!-- Bootstrap -->
 <script type="text/javascript" src="/core/bootstrap/js/bootstrap.min.js"></script>

 <!-- Bootstrap core CSS -->
 <link href="/core/bootstrap/css/bootstrap.min.css" rel="stylesheet">
 <!-- Optional Bootstrap Theme -->
 <link data-href="/core/bootstrap/css/bootstrap-theme.min.css" rel="stylesheet" id="bs-theme-stylesheet">
 <script src="../ckeditor.js"></script><!-- the editor -->
 <script type="text/javascript" src="../adapters/jquery.js"></script>
 <script src="tab4.js"></script>
</head>


Here I'm pulling all of my ingredients - plus  my own code - on board, html5-style.
Not much to see, here - we're loading the CKeditor jquery plugin for the heck of it, since we are not going to use it.

Markup: the body


<body id="main">
  <div style="width:100%; height:400px; border: 3px solid red;">
    <!--First tabset -->
    <ul class="nav nav-tabs">
      <li><a data-target="#oita" data-toggle="tab" class="editor">Italiano</a></li>
      <li><a data-target="#oeng" data-toggle="tab" class="editor">English</a></li>
      <li><a data-target="#oesp" data-toggle="tab" class="editor">Spagnolo</a></li>
      <li><a data-target="#odeu" data-toggle="tab" class="editor">Deutsch</a></li>
    </ul>
    <span style="border:3px solid #0f0;">Seleziona il testo per editare</span>
    <div class="tab-content" style="box-shadow: inset 0 0 10px #999999;border:3px solid yellow;" >
      
      <div id="oita" class="tab-pane" style="height:300px"><textarea id="ita" name="ita">Ciao!</textarea></div>
      <div id="oeng" class="tab-pane" style="height:300px"><textarea id="eng" name="eng"><i>Hello!</i></textarea></div>
      <div id="oesp" class="tab-pane" style="height:300px"><textarea id="esp" name="esp"><b>Hola!</b></textarea></div>
      <div id="odeu" class="tab-pane" style="height:300px"><textarea id="deu" name="deu"><b>Guten tag!</b></textarea></div>
      
    </div>
  </div>
</body>
</html>


The meat and potato of the UI, these is textbook stile bootstrap JS tabbing, with all its data-xxx thingies wired up just right. I am also adding an 'editor' class to seize upon later with a jquery selector, and a few containers and visual cues that will tell the user that yes - click the text and editing will happen.

Javascript: the wiring

It is now time to sprinkle our  jquery magic ppowder, tucked away in tab4.js (yes, the fourth iteration):

$(document).ready( function() {    
    CKEDITOR.config.height = 150;
    CKEDITOR.config.width = 'auto';
  $('.editor').on('shown.bs.tab', function (e) {
 var target = $($(this).data("target"));
 target.find('textarea').each(function () {
     if(!CKEDITOR.instances[this.id]) {
  CKEDITOR.inline(this);
     }
 });
 return 1;
    });
});


A bit of explanation is in order, here.

  1. $(document).ready(): wrap everyhting inside this. No need to worry, I can register as many ready- handlers as you like and they will fire on a first-defined, first-served basis.
  2.  $('.editor'): seize the editor-classed elements . These are the anchors that compose the links on the tabs
  3. .on('shown.bs.tab', function (e) {:  attach a callback to the "expose" event . the funky event name took me forever to locate
  4. $($(this).data("target")): select the target that will be exposed (it is one of the divs, see markup). Is this syntax bit ugly, or what?
  5. target.find('textarea').each(function () {: iterate on the descended textares (better have one per container, or there goes  your efficiencies
  6. if(!CKEDITOR.instances[this.id]) { CKEDITOR.inline(this): if it does not already contain an editor, create it.
Six easy pieces.

Catharsis

And there you have it. Efficient CKeditor tabbing

Tuesday, July 7, 2015

Cicale Greche, formiche Europee?


"Le conseguenze finanziarie di un'uscita Grecia dall'Euro oggi possono essere valutate con più tranquillità che in passato perché il rischio di contagio è molto inferiore a di quanto non fosse in passato [...]
Il sistema bancario europeo, che è il più probabile portatore di contagio nel corso delle crisi finanziarie, è in uno stato migliore che non all'inizio della crisi. Le banche dell'Eurozona hanno accumulato 250 miliardi di capitale dal 2008, rafforzando una situazione contabile poco solida. Le banche che erano pesantemente esposte al debito Greco hanno avuto tutto il tempo di riordinare i propri bilanci. Secondo Deutsche Bank,  l'esposizione dei i creditori (privati, NdR) Europei, un tempo pari a quasi 300 miliardi,  è ora di circa 54 miliardi. La maggior parte del debito greco è ora nelle mani dei governi e di istituzioni internazionali, che sono in grado di sopportare i costi di un'insolvenza greca, cosa che le banche non potrebbero fare.  Il costo dell'uscita della Grecia dall'euro potrebbe essere 230 miliardi di Euro, secondo le stime di Alberto Gallo di RBS - un bella cifra, ma solo il 2% del PIL Europeo"

"The financial consequences of Greece leaving the euro can now be considered with much more equanimity than previously because the risk of contagion looks much smaller than it used to. [...]Europe’s banking system, a likely vector for contagion in any financial crisis, is in better shape than at the outset of the crisis. Euro-zone banks have raised some €250 billion in capital since 2008, bolstering once-shaky balance sheets. And banks once heavily exposed to Greece have had ample time to reorder their affairs. European lenders’ claims on Greece, which once topped €300 billion, now stand at just €54 billion, according to Deutsche Bank. Most of the outstanding Greek debt is now owed to governments and international institutions, which could handle the cost of default, rather than to banks, which would struggle to do so. The overall cost of Grexit might be €230 billion, according to Alberto Gallo of RBS, another bank: hefty, but only about 2% of euro-zone GDP."

(Tratto da "The Greek crisis-There comes up a day" The Economist, 4/07/2015 - sottolineature aggiunte) 

Chi crede che la crisi Greca sia solo una favola morale in cui una cicala (greca) chiede alle formiche (europee) di pagare per i propri vizi estivi può dare un'occhiata al brano citato poco sopra.  In sintesi: nel 2012 la Grexit era impensabile perché il debito Greco era in gran parte in mani private,ora si può pensare perché in questi tre anni il suo costo è stato trasferito dalle banche (Goldman Sachs, tra le altre) ai governi - cioè a noi.

Non c'è da scandalizzarsene più di tanto, visto che nonostante le perplessità di alcuni commentatori ("Ma zio, se non brucio una banca...sono un coglione!") senza banche si sta tutti maluccio. Ma questo non significa che alle banche si debba condonare qualunque comportamento rischioso - ad esempio suggerire ad un governo i modi di truccare il proprio bilancio, cosa che la Grecia ha fatto, con il complice silenzio-assenso di tutti, fino al 2010. Si possono pewrò mettere in prospettiva i discorsi sulla responsabiltà e le spiegazioni semplificate del tipo "i debiti  vanno pagati".  

Poi i debiti vanno pagati, e la crisi Greca è anche  una favola morale di cicale greche  - solo che le formiche, se ci sono e se sono europee, non sono probabilmente tra quelli che decidono oggi cosa fare, e se ci sono, sono anche più odiose che nella favola originale.