Created
September 14, 2015 08:17
-
-
Save hnq90/3b4750122996894b7f52 to your computer and use it in GitHub Desktop.
Redactor Utils
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| utils: function() | |
| { | |
| return { | |
| isMobile: function() | |
| { | |
| return /(iPhone|iPod|BlackBerry|Android)/.test(navigator.userAgent); | |
| }, | |
| isDesktop: function() | |
| { | |
| return !/(iPhone|iPod|iPad|BlackBerry|Android)/.test(navigator.userAgent); | |
| }, | |
| isString: function(obj) | |
| { | |
| return Object.prototype.toString.call(obj) == '[object String]'; | |
| }, | |
| isEmpty: function(html, removeEmptyTags) | |
| { | |
| html = html.replace(/[\u200B-\u200D\uFEFF]/g, ''); | |
| html = html.replace(/ /gi, ''); | |
| html = html.replace(/<\/?br\s?\/?>/g, ''); | |
| html = html.replace(/\s/g, ''); | |
| html = html.replace(/^<p>[^\W\w\D\d]*?<\/p>$/i, ''); | |
| html = html.replace(/<iframe(.*?[^>])>$/i, 'iframe'); | |
| html = html.replace(/<source(.*?[^>])>$/i, 'source'); | |
| // remove empty tags | |
| if (removeEmptyTags !== false) | |
| { | |
| html = html.replace(/<[^\/>][^>]*><\/[^>]+>/gi, ''); | |
| html = html.replace(/<[^\/>][^>]*><\/[^>]+>/gi, ''); | |
| } | |
| html = $.trim(html); | |
| return html === ''; | |
| }, | |
| normalize: function(str) | |
| { | |
| if (typeof(str) === 'undefined') return 0; | |
| return parseInt(str.replace('px',''), 10); | |
| }, | |
| hexToRgb: function(hex) | |
| { | |
| if (typeof hex == 'undefined') return; | |
| if (hex.search(/^#/) == -1) return hex; | |
| var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; | |
| hex = hex.replace(shorthandRegex, function(m, r, g, b) | |
| { | |
| return r + r + g + g + b + b; | |
| }); | |
| var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); | |
| return 'rgb(' + parseInt(result[1], 16) + ', ' + parseInt(result[2], 16) + ', ' + parseInt(result[3], 16) + ')'; | |
| }, | |
| getOuterHtml: function(el) | |
| { | |
| return $('<div>').append($(el).eq(0).clone()).html(); | |
| }, | |
| getAlignmentElement: function(el) | |
| { | |
| if ($.inArray(el.tagName, this.opts.alignmentTags) !== -1) | |
| { | |
| return $(el); | |
| } | |
| else | |
| { | |
| return $(el).closest(this.opts.alignmentTags.toString().toLowerCase(), this.$editor[0]); | |
| } | |
| }, | |
| removeEmptyAttr: function(el, attr) | |
| { | |
| var $el = $(el); | |
| if (typeof $el.attr(attr) == 'undefined') | |
| { | |
| return true; | |
| } | |
| if ($el.attr(attr) === '') | |
| { | |
| $el.removeAttr(attr); | |
| return true; | |
| } | |
| return false; | |
| }, | |
| removeEmpty: function(i, s) | |
| { | |
| var $s = $($.parseHTML(s)); | |
| $s.find('.redactor-invisible-space').removeAttr('style').removeAttr('class'); | |
| if ($s.find('hr, br, img, iframe, source').length !== 0) return; | |
| var text = $.trim($s.text()); | |
| if (this.utils.isEmpty(text, false)) | |
| { | |
| $s.remove(); | |
| } | |
| }, | |
| // save and restore scroll | |
| saveScroll: function() | |
| { | |
| this.saveEditorScroll = this.$editor.scrollTop(); | |
| this.saveBodyScroll = $(window).scrollTop(); | |
| if (this.opts.scrollTarget) this.saveTargetScroll = $(this.opts.scrollTarget).scrollTop(); | |
| }, | |
| restoreScroll: function() | |
| { | |
| if (typeof this.saveScroll === 'undefined' && typeof this.saveBodyScroll === 'undefined') return; | |
| $(window).scrollTop(this.saveBodyScroll); | |
| this.$editor.scrollTop(this.saveEditorScroll); | |
| if (this.opts.scrollTarget) $(this.opts.scrollTarget).scrollTop(this.saveTargetScroll); | |
| }, | |
| // get invisible space element | |
| createSpaceElement: function() | |
| { | |
| var space = document.createElement('span'); | |
| space.className = 'redactor-invisible-space'; | |
| space.innerHTML = this.opts.invisibleSpace; | |
| return space; | |
| }, | |
| // replace | |
| removeInlineTags: function(node) | |
| { | |
| var tags = this.opts.inlineTags; | |
| tags.push('span'); | |
| if (node.tagName == 'PRE') tags.push('a'); | |
| $(node).find(tags.join(',')).not('span.redactor-selection-marker').contents().unwrap(); | |
| }, | |
| replaceWithContents: function(node, removeInlineTags) | |
| { | |
| var self = this; | |
| $(node).replaceWith(function() | |
| { | |
| if (removeInlineTags === true) self.utils.removeInlineTags(this); | |
| return $(this).contents(); | |
| }); | |
| return $(node); | |
| }, | |
| replaceToTag: function(node, tag, removeInlineTags) | |
| { | |
| var replacement; | |
| var self = this; | |
| $(node).replaceWith(function() | |
| { | |
| replacement = $('<' + tag + ' />').append($(this).contents()); | |
| for (var i = 0; i < this.attributes.length; i++) | |
| { | |
| replacement.attr(this.attributes[i].name, this.attributes[i].value); | |
| } | |
| if (removeInlineTags === true) self.utils.removeInlineTags(replacement); | |
| return replacement; | |
| }); | |
| return replacement; | |
| }, | |
| // start and end of element | |
| isStartOfElement: function() | |
| { | |
| var block = this.selection.getBlock(); | |
| if (!block) return false; | |
| var offset = this.caret.getOffsetOfElement(block); | |
| return (offset === 0) ? true : false; | |
| }, | |
| isEndOfElement: function(element) | |
| { | |
| if (typeof element == 'undefined') | |
| { | |
| var element = this.selection.getBlock(); | |
| if (!element) return false; | |
| } | |
| var offset = this.caret.getOffsetOfElement(element); | |
| var text = $.trim($(element).text()).replace(/\n\r\n/g, ''); | |
| return (offset == text.length) ? true : false; | |
| }, | |
| isStartOfEditor: function() | |
| { | |
| var offset = this.caret.getOffsetOfElement(this.$editor[0]); | |
| return (offset === 0) ? true : false; | |
| }, | |
| isEndOfEditor: function() | |
| { | |
| var block = this.$editor[0]; | |
| var offset = this.caret.getOffsetOfElement(block); | |
| var text = $.trim($(block).html().replace(/(<([^>]+)>)/gi,'')); | |
| return (offset == text.length) ? true : false; | |
| }, | |
| // test blocks | |
| isBlock: function(block) | |
| { | |
| block = block[0] || block; | |
| return block && this.utils.isBlockTag(block.tagName); | |
| }, | |
| isBlockTag: function(tag) | |
| { | |
| if (typeof tag == 'undefined') return false; | |
| return this.reIsBlock.test(tag); | |
| }, | |
| // tag detection | |
| isTag: function(current, tag) | |
| { | |
| var element = $(current).closest(tag, this.$editor[0]); | |
| if (element.length == 1) | |
| { | |
| return element[0]; | |
| } | |
| return false; | |
| }, | |
| // select all | |
| isSelectAll: function() | |
| { | |
| return this.selectAll; | |
| }, | |
| enableSelectAll: function() | |
| { | |
| this.selectAll = true; | |
| }, | |
| disableSelectAll: function() | |
| { | |
| this.selectAll = false; | |
| }, | |
| // parents detection | |
| isRedactorParent: function(el) | |
| { | |
| if (!el) | |
| { | |
| return false; | |
| } | |
| if ($(el).parents('.redactor-editor').length === 0 || $(el).hasClass('redactor-editor')) | |
| { | |
| return false; | |
| } | |
| return el; | |
| }, | |
| isCurrentOrParentHeader: function() | |
| { | |
| return this.utils.isCurrentOrParent(['H1', 'H2', 'H3', 'H4', 'H5', 'H6']); | |
| }, | |
| isCurrentOrParent: function(tagName) | |
| { | |
| var parent = this.selection.getParent(); | |
| var current = this.selection.getCurrent(); | |
| if ($.isArray(tagName)) | |
| { | |
| var matched = 0; | |
| $.each(tagName, $.proxy(function(i, s) | |
| { | |
| if (this.utils.isCurrentOrParentOne(current, parent, s)) | |
| { | |
| matched++; | |
| } | |
| }, this)); | |
| return (matched === 0) ? false : true; | |
| } | |
| else | |
| { | |
| return this.utils.isCurrentOrParentOne(current, parent, tagName); | |
| } | |
| }, | |
| isCurrentOrParentOne: function(current, parent, tagName) | |
| { | |
| tagName = tagName.toUpperCase(); | |
| return parent && parent.tagName === tagName ? parent : current && current.tagName === tagName ? current : false; | |
| }, | |
| // browsers detection | |
| isOldIe: function() | |
| { | |
| return (this.utils.browser('msie') && parseInt(this.utils.browser('version'), 10) < 9) ? true : false; | |
| }, | |
| isLessIe10: function() | |
| { | |
| return (this.utils.browser('msie') && parseInt(this.utils.browser('version'), 10) < 10) ? true : false; | |
| }, | |
| isIe11: function() | |
| { | |
| return !!navigator.userAgent.match(/Trident\/7\./); | |
| }, | |
| browser: function(browser) | |
| { | |
| var ua = navigator.userAgent.toLowerCase(); | |
| var match = /(opr)[\/]([\w.]+)/.exec( ua ) || | |
| /(chrome)[ \/]([\w.]+)/.exec( ua ) || | |
| /(webkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || | |
| /(webkit)[ \/]([\w.]+)/.exec( ua ) || | |
| /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) || | |
| /(msie) ([\w.]+)/.exec( ua ) || | |
| ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec( ua ) || | |
| ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) || | |
| []; | |
| if (browser == 'safari') return (typeof match[3] != 'undefined') ? match[3] == 'safari' : false; | |
| if (browser == 'version') return match[2]; | |
| if (browser == 'webkit') return (match[1] == 'chrome' || match[1] == 'opr' || match[1] == 'webkit'); | |
| if (match[1] == 'rv') return browser == 'msie'; | |
| if (match[1] == 'opr') return browser == 'webkit'; | |
| return browser == match[1]; | |
| }, | |
| strpos: function(haystack, needle, offset) | |
| { | |
| var i = haystack.indexOf(needle, offset); | |
| return i >= 0 ? i : false; | |
| }, | |
| disableBodyScroll: function() | |
| { | |
| var $body = $('html'); | |
| var windowWidth = window.innerWidth; | |
| if (!windowWidth) | |
| { | |
| var documentElementRect = document.documentElement.getBoundingClientRect(); | |
| windowWidth = documentElementRect.right - Math.abs(documentElementRect.left); | |
| } | |
| var isOverflowing = document.body.clientWidth < windowWidth; | |
| var scrollbarWidth = this.utils.measureScrollbar(); | |
| $body.css('overflow', 'hidden'); | |
| if (isOverflowing) $body.css('padding-right', scrollbarWidth); | |
| }, | |
| measureScrollbar: function() | |
| { | |
| var $body = $('body'); | |
| var scrollDiv = document.createElement('div'); | |
| scrollDiv.className = 'redactor-scrollbar-measure'; | |
| $body.append(scrollDiv); | |
| var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; | |
| $body[0].removeChild(scrollDiv); | |
| return scrollbarWidth; | |
| }, | |
| enableBodyScroll: function() | |
| { | |
| $('html').css({ 'overflow': '', 'padding-right': '' }); | |
| $('body').remove('redactor-scrollbar-measure'); | |
| } | |
| }; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment