~openerp-dev/openerp-web/trunk-customfilter-jir

« back to all changes in this revision

Viewing changes to addons/web/static/lib/cleditor/jquery.cleditor.js

  • Committer: Vidhin Mehta (OpenERP)
  • Date: 2014-04-21 05:26:17 UTC
  • mfrom: (3747.2.239 trunk)
  • Revision ID: vme@tinyerp.com-20140421052617-spns3fo5ryybbwhx
[MERGE]Trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 @preserve CLEditor WYSIWYG HTML Editor v1.3.0
3
 
 http://premiumsoftware.net/cleditor
 
1
/*!
 
2
 CLEditor WYSIWYG HTML Editor v1.4.4
 
3
 http://premiumsoftware.net/CLEditor
4
4
 requires jQuery v1.4.2 or later
5
5
 
6
6
 Copyright 2010, Chris Landowski, Premium Software, LLC
7
7
 Dual licensed under the MIT or GPL Version 2 licenses.
8
8
*/
9
9
 
10
 
// ==ClosureCompiler==
11
 
// @compilation_level SIMPLE_OPTIMIZATIONS
12
 
// @output_file_name jquery.cleditor.min.js
13
 
// ==/ClosureCompiler==
14
 
 
15
 
(function($) {
 
10
(function ($) {
16
11
 
17
12
  //==============
18
13
  // jQuery Plugin
22
17
 
23
18
    // Define the defaults used for all new cleditor instances
24
19
    defaultOptions: {
25
 
      width:        500, // width not including margins, borders or padding
 
20
      width:        'auto', // width not including margins, borders or padding
26
21
      height:       250, // height not including margins, borders or padding
27
22
      controls:     // controls to add to the toolbar
28
23
                    "bold italic underline strikethrough subscript superscript | font size " +
46
41
                    [["Paragraph", "<p>"], ["Header 1", "<h1>"], ["Header 2", "<h2>"],
47
42
                    ["Header 3", "<h3>"],  ["Header 4","<h4>"],  ["Header 5","<h5>"],
48
43
                    ["Header 6","<h6>"]],
49
 
      useCSS:       false, // use CSS to style HTML when possible (not supported in ie)
 
44
      useCSS:       true, // use CSS to style HTML when possible (not supported in ie)
50
45
      docType:      // Document type contained within the editor
51
46
                    '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
52
47
      docCSSFile:   // CSS file used to style the document contained within the editor
57
52
 
58
53
    // Define all usable toolbar buttons - the init string property is 
59
54
    //   expanded during initialization back into the buttons object and 
60
 
    //   seperate object properties are created for each button.
 
55
    //   separate object properties are created for each button.
61
56
    //   e.g. buttons.size.title = "Font Size"
62
57
    buttons: {
63
58
      // name,title,command,popupName (""=use name)
109
104
 
110
105
    // Loop through all matching textareas and create the editors
111
106
    this.each(function(idx, elem) {
112
 
      if (elem.tagName == "TEXTAREA") {
 
107
      if (elem.tagName.toUpperCase() === "TEXTAREA") {
113
108
        var data = $.data(elem, CLEDITOR);
114
109
        if (!data) data = new cleditor(elem, options);
115
110
        $result = $result.add(data);
129
124
 
130
125
  // Misc constants
131
126
  BACKGROUND_COLOR = "backgroundColor",
 
127
  BLURRED          = "blurred",
132
128
  BUTTON           = "button",
133
129
  BUTTON_NAME      = "buttonName",
134
130
  CHANGE           = "change",
136
132
  CLICK            = "click",
137
133
  DISABLED         = "disabled",
138
134
  DIV_TAG          = "<div>",
 
135
  FOCUSED          = "focused",
139
136
  TRANSPARENT      = "transparent",
140
137
  UNSELECTABLE     = "unselectable",
141
138
 
152
149
  PROMPT_CLASS     = "cleditorPrompt",  // prompt popup divs inside body
153
150
  MSG_CLASS        = "cleditorMsg",     // message popup div inside body
154
151
 
155
 
  // Test for ie
156
 
  ie = $.browser.msie,
157
 
  ie6 = /msie\s6/i.test(navigator.userAgent),
 
152
  // Browser detection
 
153
  ua = navigator.userAgent.toLowerCase(),
 
154
  ie = /msie/.test(ua),
 
155
  ie6 = /msie\s6/.test(ua),
 
156
  iege11 = /(trident)(?:.*rv:([\w.]+))?/.test(ua),
 
157
  webkit = /webkit/.test(ua),
158
158
 
159
159
  // Test for iPhone/iTouch/iPad
160
 
  iOS = /iphone|ipad|ipod/i.test(navigator.userAgent),
 
160
  iOS = /iphone|ipad|ipod/i.test(ua),
161
161
 
162
162
  // Popups are created once as needed and shared by all editor instances
163
163
  popups = {},
223
223
    var $group = $(DIV_TAG)
224
224
      .addClass(GROUP_CLASS)
225
225
      .appendTo($toolbar);
 
226
 
 
227
    // Initialize the group width
 
228
    var groupWidth = 0;
226
229
    
227
230
    // Add the buttons to the toolbar
228
231
    $.each(options.controls.split(" "), function(idx, buttonName) {
229
232
      if (buttonName === "") return true;
230
233
 
231
234
      // Divider
232
 
      if (buttonName == "|") {
 
235
      if (buttonName === "|") {
233
236
 
234
237
        // Add a new divider to the group
235
238
        var $div = $(DIV_TAG)
236
239
          .addClass(DIVIDER_CLASS)
237
240
          .appendTo($group);
238
241
 
 
242
        // Update the group width
 
243
        $group.width(groupWidth + 1);
 
244
        groupWidth = 0;
 
245
 
239
246
        // Create a new group
240
247
        $group = $(DIV_TAG)
241
248
          .addClass(GROUP_CLASS)
258
265
          .appendTo($group)
259
266
          .hover(hoverEnter, hoverLeave);
260
267
 
 
268
        // Update the group width
 
269
        groupWidth += 24;
 
270
        $group.width(groupWidth + 1);
 
271
 
261
272
        // Prepare the button image
262
273
        var map = {};
263
274
        if (button.css) map = button.css;
295
306
 
296
307
    // Bind the window resize event when the width or height is auto or %
297
308
    if (/auto|%/.test("" + options.width + options.height))
298
 
      $(window).resize(function() {
 
309
      $(window).bind('resize.cleditor', function () {
299
310
        //Forcefully blurred iframe contentWindow, chrome, IE, safari doesn't trigger blur on window resize and due to which text disappears
300
311
        var contentWindow = editor.$frame[0].contentWindow;
301
312
        if(!$.browser.mozilla && contentWindow){
306
317
          refresh(editor);
307
318
        }
308
319
      });
309
 
 
310
320
    // Create the iframe and resize the controls
311
321
    refresh(editor);
312
322
 
347
357
      return editor;
348
358
    };
349
359
  });
 
360
  
 
361
  // blurred - shortcut for .bind("blurred", handler) or .trigger("blurred")
 
362
  fn.blurred = function(handler) {
 
363
    var $this = $(this);
 
364
    return handler ? $this.bind(BLURRED, handler) : $this.trigger(BLURRED);
 
365
  };
350
366
 
351
367
  // change - shortcut for .bind("change", handler) or .trigger("change")
352
 
  fn.change = function(handler) {
 
368
  fn.change = function change(handler) {
 
369
    console.log('change test');
353
370
    var $this = $(this);
354
371
    return handler ? $this.bind(CHANGE, handler) : $this.trigger(CHANGE);
355
372
  };
356
373
 
 
374
  // focused - shortcut for .bind("focused", handler) or .trigger("focused")
 
375
  fn.focused = function(handler) {
 
376
    var $this = $(this);
 
377
    return handler ? $this.bind(FOCUSED, handler) : $this.trigger(FOCUSED);
 
378
  };
 
379
 
357
380
  //===============
358
381
  // Event Handlers
359
382
  //===============
369
392
        popup = popups[popupName];
370
393
 
371
394
    // Check if disabled
372
 
    if (editor.disabled || $(buttonDiv).attr(DISABLED) == DISABLED)
 
395
    if (editor.disabled || $(buttonDiv).attr(DISABLED) === DISABLED)
373
396
      return;
374
397
 
375
398
    // Fire the buttonClick event
387
410
      return false;
388
411
 
389
412
    // Toggle source
390
 
    if (buttonName == "source") {
 
413
    if (buttonName === "source") {
391
414
 
392
415
      // Show the iframe
393
416
      if (sourceMode(editor)) {
418
441
        var $popup = $(popup);
419
442
 
420
443
        // URL
421
 
        if (popupName == "url") {
 
444
        if (popupName === "url") {
422
445
 
423
446
          // Check for selection before showing the link url popup
424
 
          if (buttonName == "link" && selectedText(editor) === "") {
 
447
          if (buttonName === "link" && selectedText(editor) === "") {
425
448
            showMessage(editor, "A selection is required when inserting a link.", buttonDiv);
426
449
            return false;
427
450
          }
447
470
        }
448
471
 
449
472
        // Paste as Text
450
 
        else if (popupName == "pastetext") {
 
473
        else if (popupName === "pastetext") {
451
474
 
452
475
          // Wire up the submit button click event handler
453
476
          $popup.children(":button")
475
498
          return false; // stop propagination to document click
476
499
        }
477
500
 
478
 
        // propaginate to documnt click
 
501
        // propaginate to document click
479
502
        return;
480
503
 
481
504
      }
482
505
 
483
506
      // Print
484
 
      else if (buttonName == "print")
 
507
      else if (buttonName === "print")
485
508
        editor.$frame[0].contentWindow.print();
486
509
 
487
510
      // All other buttons
526
549
        useCSS = editor.options.useCSS;
527
550
 
528
551
    // Get the command value
529
 
    if (buttonName == "font")
 
552
    if (buttonName === "font")
530
553
      // Opera returns the fontfamily wrapped in quotes
531
554
      value = target.style.fontFamily.replace(/"/g, "");
532
 
    else if (buttonName == "size") {
533
 
      if (target.tagName == "DIV")
 
555
    else if (buttonName === "size") {
 
556
      if (target.tagName.toUpperCase() === "DIV")
534
557
        target = target.children[0];
535
558
      value = target.innerHTML;
536
559
    }
537
 
    else if (buttonName == "style")
 
560
    else if (buttonName === "style")
538
561
      value = "<" + target.tagName + ">";
539
 
    else if (buttonName == "color")
 
562
    else if (buttonName === "color")
540
563
      value = hex(target.style.backgroundColor);
541
 
    else if (buttonName == "highlight") {
 
564
    else if (buttonName === "highlight") {
542
565
      value = hex(target.style.backgroundColor);
543
566
      if (ie) command = 'backcolor';
544
567
      else useCSS = true;
610
633
      $popup.html(popupContent);
611
634
 
612
635
    // Color
613
 
    else if (popupName == "color") {
 
636
    else if (popupName === "color") {
614
637
      var colors = options.colors.split(" ");
615
638
      if (colors.length < 10)
616
639
        $popup.width("auto");
622
645
    }
623
646
 
624
647
    // Font
625
 
    else if (popupName == "font")
 
648
    else if (popupName === "font")
626
649
      $.each(options.fonts.split(","), function(idx, font) {
627
650
        $(DIV_TAG).appendTo($popup)
628
651
          .css("fontFamily", font)
630
653
      });
631
654
 
632
655
    // Size
633
 
    else if (popupName == "size")
 
656
    else if (popupName === "size")
634
657
      $.each(options.sizes.split(","), function(idx, size) {
635
658
        $(DIV_TAG).appendTo($popup)
636
 
          .html("<font size=" + size + ">" + size + "</font>");
 
659
          .html('<font size="' + size + '">' + size + '</font>');
637
660
      });
638
661
 
639
662
    // Style
640
 
    else if (popupName == "style")
 
663
    else if (popupName === "style")
641
664
      $.each(options.styles, function(idx, style) {
642
665
        $(DIV_TAG).appendTo($popup)
643
666
          .html(style[1] + style[0] + style[1].replace("<", "</"));
644
667
      });
645
668
 
646
669
    // URL
647
 
    else if (popupName == "url") {
648
 
      $popup.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');
 
670
    else if (popupName === "url") {
 
671
      $popup.html('Enter URL:<br /><input type="text" value="http://" size="35" /><br /><input type="button" value="Submit" />');
649
672
      popupTypeClass = PROMPT_CLASS;
650
673
    }
651
674
 
652
675
    // Paste as Text
653
 
    else if (popupName == "pastetext") {
654
 
      $popup.html('Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>');
 
676
    else if (popupName === "pastetext") {
 
677
      $popup.html('Paste your content here and click submit.<br /><textarea cols="40" rows="3"></textarea><br /><input type="button" value="Submit" />');
655
678
      popupTypeClass = PROMPT_CLASS;
656
679
    }
657
680
 
720
743
    }
721
744
 
722
745
    // Execute the command and check for error
723
 
    var success = true, description;
724
 
    if (ie && command.toLowerCase() == "inserthtml")
 
746
    var success = true, message;
 
747
    if (ie && command.toLowerCase() === "inserthtml")
725
748
      getRange(editor).pasteHTML(value);
726
749
    else {
727
750
      try { success = editor.doc.execCommand(command, 0, value || null); }
728
 
      catch (err) { description = err.description; success = false; }
 
751
      catch (err) { message = err.message; success = false; }
729
752
      if (!success) {
730
753
        if ("cutcopypaste".indexOf(command) > -1)
731
754
          showMessage(editor, "For security reasons, your browser does not support the " +
733
756
            button);
734
757
        else
735
758
          showMessage(editor,
736
 
            (description ? description : "Error executing the " + command + " command."),
 
759
            (message ? message : "Error executing the " + command + " command."),
737
760
            button);
738
761
      }
739
762
    }
740
763
 
741
 
    // Enable the buttons
 
764
    // Enable the buttons and update the textarea
742
765
    refreshButtons(editor);
 
766
    updateTextArea(editor, true);
743
767
    return success;
744
768
 
745
769
  }
765
789
    return editor.$frame[0].contentWindow.getSelection();
766
790
  }
767
791
 
768
 
  // Returns the hex value for the passed in string.
769
 
  //   hex("rgb(255, 0, 0)"); // #FF0000
770
 
  //   hex("#FF0000"); // #FF0000
771
 
  //   hex("#F00"); // #FF0000
 
792
  // hex - returns the hex value for the passed in color string
772
793
  function hex(s) {
773
 
    var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s),
774
 
      c = s.split("");
 
794
 
 
795
    // hex("rgb(255, 0, 0)") returns #FF0000
 
796
    var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s);
775
797
    if (m) {
776
 
      s = ( m[1] << 16 | m[2] << 8 | m[3] ).toString(16);
 
798
      s = (m[1] << 16 | m[2] << 8 | m[3]).toString(16);
777
799
      while (s.length < 6)
778
800
        s = "0" + s;
 
801
      return "#" + s;
779
802
    }
780
 
    return "#" + (s.length == 6 ? s : c[1] + c[1] + c[2] + c[2] + c[3] + c[3]);
 
803
 
 
804
    // hex("#F00") returns #FF0000
 
805
    var c = s.split("");
 
806
    if (s.length === 4)
 
807
      return "#" + c[1] + c[1] + c[2] + c[2] + c[3] + c[3];
 
808
 
 
809
    // hex("#FF0000") returns #FF0000
 
810
    return s;
 
811
 
781
812
  }
782
813
 
783
814
  // hidePopups - hides all popups
792
823
 
793
824
  // imagesPath - returns the path to the images folder
794
825
  function imagesPath() {
795
 
    var cssFile = "jquery.cleditor.css",
796
 
        href = $("link[href$='" + cssFile +"']").attr("href");
797
 
    return href.substr(0, href.length - cssFile.length) + "images/";
 
826
    var href = $("link[href*=cleditor]").attr("href");
 
827
    return href.replace(/^(.*\/)[^\/]+$/, '$1') + "images/";
798
828
  }
799
829
 
800
830
  // imageUrl - Returns the css url string for a filemane
813
843
      editor.$frame.remove();
814
844
 
815
845
    // Create a new iframe
816
 
    var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;">')
 
846
    var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;" />')
817
847
      .hide()
818
848
      .appendTo($main);
819
849
 
833
863
 
834
864
    // Work around for bug in IE which causes the editor to lose
835
865
    // focus when clicking below the end of the document.
836
 
    if (ie)
 
866
    if (ie || iege11)
837
867
      $doc.click(function() {focus(editor);});
838
868
 
839
869
    // Load the content
840
870
    updateFrame(editor);
841
871
 
842
872
    // Bind the ie specific iframe event handlers
843
 
    if (ie) {
 
873
    if (ie || iege11) {
844
874
 
845
875
      // Save the current user selection. This code is needed since IE will
846
876
      // reset the selection just after the beforedeactivate event and just
848
878
      $doc.bind("beforedeactivate beforeactivate selectionchange keypress", function(e) {
849
879
        
850
880
        // Flag the editor as inactive
851
 
        if (e.type == "beforedeactivate")
 
881
        if (e.type === "beforedeactivate")
852
882
          editor.inactive = true;
853
 
        
854
 
        // Get rid of the bogus selection and flag the editor as active
855
 
        else if (e.type == "beforeactivate") {
 
883
 
 
884
          // Get rid of the bogus selection and flag the editor as active
 
885
        else if (e.type === "beforeactivate") {
856
886
          if (!editor.inactive && editor.range && editor.range.length > 1)
857
887
            editor.range.shift();
858
888
          delete editor.inactive;
859
889
        }
860
890
 
861
 
        // Save the selection when the editor is active
 
891
          // Save the selection when the editor is active
862
892
        else if (!editor.inactive) {
863
 
          if (!editor.range) 
 
893
          if (!editor.range)
864
894
            editor.range = [];
865
895
          editor.range.unshift(getRange(editor));
866
896
 
871
901
 
872
902
      });
873
903
 
874
 
      // Restore the text range when the iframe gains focus
 
904
      // Restore the text range and trigger focused event when the iframe gains focus
875
905
      $frame.focus(function() {
876
906
        restoreRange(editor);
877
 
      });
878
 
 
879
 
    }
880
 
 
881
 
    // Update the textarea when the iframe loses focus
882
 
    ($.browser.mozilla ? $doc : $(contentWindow)).blur(function() {
883
 
      updateTextArea(editor, true);
884
 
    });
885
 
 
886
 
    // Enable the toolbar buttons as the user types or clicks
 
907
        $(editor).triggerHandler(FOCUSED);
 
908
      });
 
909
 
 
910
      // Trigger blurred event when the iframe looses focus
 
911
      $frame.blur(function() {
 
912
        $(editor).triggerHandler(BLURRED);
 
913
      });
 
914
 
 
915
    }
 
916
 
 
917
      // Trigger focused and blurred events for all other browsers
 
918
    else {
 
919
      $(editor.$frame[0].contentWindow)
 
920
        .focus(function () { $(editor).triggerHandler(FOCUSED); })
 
921
        .blur(function () { $(editor).triggerHandler(BLURRED); });
 
922
    }
 
923
 
 
924
    // Enable the toolbar buttons and update the textarea as the user types or clicks
887
925
    $doc.click(hidePopups)
888
926
      .bind("keyup mouseup", function() {
889
927
        refreshButtons(editor);
 
928
        updateTextArea(editor, true);
890
929
      });
891
930
 
892
931
    // Show the textarea for iPhone/iTouch/iPad or
906
945
      $toolbar.height(hgt);
907
946
 
908
947
      // Resize the iframe
909
 
      hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height)) - hgt;
 
948
      hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height, 10)) - hgt;
910
949
      $frame.width(wid).height(hgt);
911
950
 
912
951
      // Resize the textarea. IE6 textareas have a 1px top
927
966
  function refreshButtons(editor) {
928
967
 
929
968
    // Webkit requires focus before queryCommandEnabled will return anything but false
930
 
    if (!iOS && $.browser.webkit && !editor.focused) {
 
969
    if (!iOS && webkit && !editor.focused) {
931
970
      editor.$frame[0].contentWindow.focus();
932
971
      window.focus();
933
972
      editor.focused = true;
963
1002
        if (enabled === undefined)
964
1003
          enabled = true;
965
1004
      }
966
 
      else if (((inSourceMode || iOS) && button.name != "source") ||
967
 
      (ie && (command == "undo" || command == "redo")))
 
1005
      else if (((inSourceMode || iOS) && button.name !== "source") ||
 
1006
      (ie && (command === "undo" || command === "redo")))
968
1007
        enabled = false;
969
 
      else if (command && command != "print") {
970
 
        if (ie && command == "hilitecolor")
 
1008
      else if (command && command !== "print") {
 
1009
        if (ie && command === "hilitecolor")
971
1010
          command = "backcolor";
972
1011
        // IE does not support inserthtml, so it's always enabled
973
 
        if (!ie || command != "inserthtml") {
 
1012
        if (!ie || command !== "inserthtml") {
974
1013
          try {enabled = queryObj.queryCommandEnabled(command);}
975
1014
          catch (err) {enabled = false;}
976
1015
        }
991
1030
 
992
1031
  // restoreRange - restores the current ie selection
993
1032
  function restoreRange(editor) {
994
 
    if (ie && editor.range)
995
 
      editor.range[0].select();
 
1033
    if (editor.range) {
 
1034
      if (ie)
 
1035
        editor.range[0].select();
 
1036
      else if (iege11)
 
1037
        getSelection(editor).addRange(editor.range[0]);
 
1038
    }
996
1039
  }
997
1040
 
998
1041
  // select - selects all the text in either the textarea or iframe
1084
1127
    // of potentially heavy updateFrame callbacks.
1085
1128
    if (updateFrameCallback) {
1086
1129
      var sum = checksum(code);
1087
 
      if (checkForChange && editor.areaChecksum == sum)
 
1130
      if (checkForChange && editor.areaChecksum === sum)
1088
1131
        return;
1089
1132
      editor.areaChecksum = sum;
1090
1133
    }
1100
1143
      editor.frameChecksum = checksum(html);
1101
1144
 
1102
1145
    // Update the iframe and trigger the change event
1103
 
    if (html != $body.html()) {
 
1146
    if (html !== $body.html()) {
1104
1147
      $body.html(html);
1105
1148
      $(editor).triggerHandler(CHANGE);
1106
1149
    }
1119
1162
    // of potentially heavy updateTextArea callbacks.
1120
1163
    if (updateTextAreaCallback) {
1121
1164
      var sum = checksum(html);
1122
 
      if (checkForChange && editor.frameChecksum == sum)
 
1165
      if (checkForChange && editor.frameChecksum === sum)
1123
1166
        return;
1124
1167
      editor.frameChecksum = sum;
1125
1168
    }
1132
1175
      editor.areaChecksum = checksum(code);
1133
1176
 
1134
1177
    // Update the textarea and trigger the change event
1135
 
    if (code != $area.val()) {
 
1178
    if (code !== $area.val()) {
1136
1179
      $area.val(code);
1137
1180
      $(editor).triggerHandler(CHANGE);
1138
1181
    }