').append(selectedText).html();
// Also select the tag
if(text.nodeType === Node.TEXT_NODE){
text = text.parentNode;
}
if (text.innerHTML === selectedText && text != t.editor[0]) {
var ele = jQuery(text);
if('tag' in btn){
// Replace tag
}else if('style' in btn){
var style = {};
style[btn.style] = value;
ele.css(style);
}else if('atts' in btn){
// Add attribute or toggle the element
}
} else {
// TODO for toggle tags and add tags
var html = jQuery('
' + selectedText + '');
// Remove style from all childrend
var style = {};
style[btn.style] = '';
html.find('[style]').css(style);
// TODO: remove span element that have no atts
var node = html[0];
var firstInsertedNode = node.firstChild;
var lastInsertedNode = node.lastChild;
t.range.deleteContents();
t.range.insertNode(node);
if(firstInsertedNode) {
t.range.setStartBefore(firstInsertedNode);
t.range.setEndAfter(lastInsertedNode);
}
// Is previous element empty?
var prev = jQuery(node).prev();
if( prev.length > 0 && prev.is(':empty') ){
prev.remove();
}
}
sel.removeAllRanges();
sel.addRange(t.range);
}
formatBlock(value){
var t = this,
format = t.currentFormat,
btn = t.handlers[format],
startNode = t.range.startContainer,
endNode = t.range.endContainer;
if( startNode.nodeType == Node.TEXT_NODE && startNode.parentNode != t.editor[0] ){
startNode = startNode.parentNode;
}
if( endNode.nodeType == Node.TEXT_NODE && endNode.parentNode != t.editor[0] ){
endNode = endNode.parentNode;
}
// TODO: only for seleced content
// Wrap text nodes in span for easier processing
t.editor.contents().filter(function () {
return this.nodeType === 3 && this.nodeValue.trim().length > 0;
}).wrap('
');
var isLineEnd = function(lEle){
return lEle == null || lEle.nodeName == 'BR' || t.isline(lEle);
}
var wrapLine = function(pLine){
var pLine = jQuery(pLine),
lineFele,
lineEele,
finalP;
// Get Parent Element
if(pLine.parentsUntil(t.editor).length > 0){
pLine = pLine.parentsUntil(t.editor).last();
}
if(t.isline(pLine)){
return pLine;
}
// Get line first element
if(isLineEnd(pLine[0].previousSibling)){
lineFele = pLine;
}else{
lineFele = pLine.prevAll().filter(function(){
return isLineEnd(this.previousSibling);
}).first();
}
// Get line last element
if(isLineEnd(lineFele[0].nextSibling)){
lineEele = lineFele;
}else{
lineEele = lineFele.nextAll().filter(function(){
return isLineEnd(this.nextSibling);
}).first();
}
// Wrap all with p tag
if(lineFele.is(lineEele)){
finalP = lineFele.wrap('
').parent()
}else{
finalP = lineFele.nextUntil(lineEele.next()).addBack().wrapAll('
').parent();
}
finalP.next('br').remove();
return finalP;
}
// Get start block lavel elements
var $sNode = jQuery(t.blockNode(startNode));
if($sNode.is(t.editor)){
$sNode = wrapLine(startNode);
}
var $eNode = jQuery(t.blockNode(endNode));
if($eNode.is(t.editor)){
$eNode = wrapLine(endNode);
}
var $oldEle = $sNode;
if(! $sNode.is($eNode) ){
var findEnd = false;
var addElement = function(addEle){
if(addEle[0].nodeName == 'UL' || addEle[0].nodeName == 'OL') {
addEle.children().each(function(){
$oldEle = $oldEle.add(jQuery(this));
});
return;
}
$oldEle = $oldEle.add(addEle);
}
var wrapAllEle = function(nextEle){
if(nextEle.is($eNode) || nextEle.find($eNode).length > 0){
findEnd = true;
return;
}
if(nextEle.length < 1){
return;
}
if(!t.isline(nextEle[0])){
nextEle = wrapLine(nextEle);
}
addElement(nextEle);
wrapAllEle( nextEle.next() );
}
wrapAllEle($sNode.next());
// Is start Element have a another parent
var pars = $sNode.parentsUntil(t.editor);
pars.each(function(){
var $par = jQuery(this);
wrapAllEle($par.next());
});
if( pars.length > 0 ){
$sNode = pars.last();
}
var nextEnd = $sNode.nextAll().filter(function(){
return jQuery(this).is($eNode) || jQuery(this).find($eNode).length > 0;
}).first();
// Add elements
if( nextEnd.length > 0 ){
var $nextEle = $sNode.nextUntil(nextEnd);
$nextEle.each(function(){
var ulEle = jQuery(this);
if($oldEle.has(ulEle)) return;
addElement(ulEle);
});
}
// Add end element
if(nextEnd.length > 0 && !nextEnd.is($eNode) && (nextEnd[0].nodeName == 'UL' || nextEnd[0].nodeName == 'OL')){
nextEnd.children().each(function(){
var li = jQuery(this);
$oldEle = $oldEle.add(li);
if(li.is($eNode) || li.find($eNode).length > 0) return false;
});
}else{
$oldEle = $oldEle.add($eNode);
}
}
if('style' in btn){
var style = {};
style[btn.style] = value;
$oldEle.css(style);
}else if('atts' in btn){
// Add attribute or toggle the element
var attr = {};
attr[btn.atts] = value;
$oldEle.attr(attr);
}else{
// Replace tag
var tag = value.toLowerCase();
// need to find all block ele and replace this
$oldEle.each( function(){
var $cEle = jQuery(this);
if($cEle.is(t.editor)){
return;
}
// Is List element
if($cEle.css('display') == 'list-item'){
if( t.isline($cEle[0].firstChild)){
$cEle.children().each(function(){
var liChild = jQuery(this);
if(t.isline(liChild[0])){
t.replaceTag(liChild, tag, true);
return;
}
// TODO: Check and need to correct
liChild.wrap('<' + tag + '/>');
liChild.next('br').remove();
});
return
}
$cEle.contents().wrapAll('<' + tag + '/>');
return;
}
t.replaceTag($cEle, tag, true);
});
}
// Get rid of pen temporary span's
jQuery('[data-pts]', t.editor).contents().unwrap();
t.semanticCode();
t.restoreRange();
}
blockNode( node ){
var t = this;
while( !t.isline(node) && node != t.editor[0] ) {
node = node.parentNode;
}
return node;
}
isline(node){
if (node.nodeType !== Node.ELEMENT_NODE) return false;
if (node.childNodes.length === 0) return false; // Exclude embed blocks
var style = window.getComputedStyle(node);
return ['block', 'list-item'].indexOf(style.display) > -1;
}
replaceTag(ele, tag, copyAttr){
ele.wrap('<' + tag + '/>');
var par = ele.parent();
if(copyAttr){
jQuery.each(ele.prop('attributes'), function () {
par.attr(this.name, this.value);
});
}
ele.contents().unwrap();
return par;
}
semanticCode(){
var t = this;
t.semanticTag('b');
t.semanticTag('i');
t.semanticTag('s');
t.semanticTag('strike');
t.semanticTag('div', true);
}
semanticTag(oldTag, copyAttributes){
var t = this;
var newTag;
if(t.semantic != null && typeof t.semantic === 'object' && t.semantic.hasOwnProperty(oldTag)){
newTag = t.semantic[oldTag];
} else if (t.DEFAULT_SEMANTIC_MAP.hasOwnProperty(oldTag)) {
newTag = t.DEFAULT_SEMANTIC_MAP[oldTag];
} else {
return;
}
jQuery(oldTag, t.editor).each(function () {
var $oldTag = jQuery(this);
if($oldTag.contents().length === 0) {
return false;
}
t.replaceTag($oldTag, newTag, copyAttributes);
});
}
addEvents(){
// Add Events
var t = this,
editor = t.editor,
ctrl = false,
debounceButtonStatus;
var showToolBar = function(){
var jEle = t.penHolder.children(':visible');
if(jEle.length < 1){
jEle = t.toolbar;
}
t.showPen(jEle);
};
// Save rage
editor.on('focusout', function(e){
if(t.destroyEd){
t.editor.removeClass('pagelayer-pen-focused');
t.range = null;
return;
}
t.saveRange();
});
// Prevent to hide toolbar
t.penHolder.on('mousedown', function(e){
// TODO: taget only require Element
t.destroyEd = false;
});
// On editor blur
editor.on('blur', function(){
if(!t.destroyEd){
return;
}
t.destroy();
});
editor.on('keydown', function(){
t.penHolder.hide();
});
editor.on('mousedown', function(){
if(t.editor.attr('contenteditable') == 'true'){
t.showPen();
}
});
editor.on('mouseup keyup keydown', function(e){
if ((!e.ctrlKey && !e.metaKey) || e.altKey) {
setTimeout(function () { // "hold on" to the ctrl key for 50ms
ctrl = false;
}, 50);
}
clearTimeout(debounceButtonStatus);
debounceButtonStatus = setTimeout(function () {
t.updateButtonStatus();
}, 50);
});
// Set focus on editor
editor.on('click', function(e){
if(t.editor.hasClass('pagelayer-pen-focused')){
return;
}
t.editor.attr('contenteditable', 'true');
t.editor.focus();
});
// Set focus on editor
editor.on('focus', function(){
t.destroyEd = true;
t.addToolbar();
t.showPen();
t.editor.addClass('pagelayer-pen-focused');
jQuery(window).unbind('scroll.penToobar');
jQuery(window).on('scroll.penToobar', showToolBar);
jQuery(document).unbind('mousemove.penToobar');
jQuery(document).on('mousemove.penToobar', showToolBar);
});
t.semanticCode();
}
destroy(){
var t = this;
//t.editor.attr('contenteditable', '');
t.penHolder.hide();
// Removing event listeners
jQuery(document).unbind('mousemove.penToobar');
jQuery(window).unbind('scroll.penToobar');
}
hasFocus(){
var t = this;
return (
t.doc.activeElement === t.editor ||
t.contains( t.editor[0], t.doc.activeElement)
);
}
contains(parent, descendant) {
try {
// Firefox inserts inaccessible nodes around video elements
descendant.parentNode; // eslint-disable-line no-unused-expressions
} catch (e) {
return false;
}
return parent.contains(descendant);
}
saveRange(){
var t = this,
selection = t.doc.getSelection();
t.range = null;
if (!selection || !selection.rangeCount) {
return;
}
var savedRange = t.range = selection.getRangeAt(0),
range = t.doc.createRange(),
rangeStart;
range.selectNodeContents(t.editor[0]);
range.setEnd(savedRange.startContainer, savedRange.startOffset);
rangeStart = (range + '').length;
t.metaRange = {
start: rangeStart,
end: rangeStart + (savedRange + '').length
};
}
restoreRange(){
var t = this,
metaRange = t.metaRange,
savedRange = t.range,
selection = t.doc.getSelection(),
range;
if(!savedRange){
return;
}
if(metaRange && metaRange.start !== metaRange.end){ // Algorithm from http://jsfiddle.net/WeWy7/3/
var charIndex = 0,
nodeStack = [t.editor[0]],
node,
foundStart = false,
stop = false;
range = t.doc.createRange();
while(!stop && (node = nodeStack.pop())){
if (node.nodeType === 3){
var nextCharIndex = charIndex + node.length;
if (!foundStart && metaRange.start >= charIndex && metaRange.start <= nextCharIndex) {
range.setStart(node, metaRange.start - charIndex);
foundStart = true;
}
if (foundStart && metaRange.end >= charIndex && metaRange.end <= nextCharIndex) {
range.setEnd(node, metaRange.end - charIndex);
stop = true;
}
charIndex = nextCharIndex;
} else {
var cn = node.childNodes,
i = cn.length;
while (i > 0) {
i -= 1;
nodeStack.push(cn[i]);
}
}
}
}
selection.removeAllRanges();
selection.addRange(range || savedRange);
}
getRange(){
var t = this;
var selection = t.doc.getSelection();
if (selection == null || selection.rangeCount <= 0) return null;
var range = selection.getRangeAt(0);
if(range == null) return null;
return range;
}
getRangeText(range){
return range + '';
}
focus(){
var t = this;
if(t.hasFocus()) return;
t.editor.click();
t.editor.focus();
t.restoreRange();
}
getBounds(range){
var rect = range.getBoundingClientRect();
return {
bottom: rect.top + rect.height,
height: rect.height,
left: rect.left,
right: rect.right,
top: rect.top,
width: 0
};
}
showPen(jEle){
var t = this;
jEle = jEle || jQuery(t.toolbar);
var toolBar = jQuery(t.penHolder);
var tooltipHeight = parseInt(toolBar.css('height'));
var range = null;
if(! t.hasFocus() && t.range != null){
range = t.range;
}else{
range = t.getRange();
}
if(range == null){
toolBar.hide();
return;
}
// Set left of toolbar
var editorOffset = t.editor[0].getBoundingClientRect();
var editorTop = editorOffset.top;
var editorLeft = editorOffset.left;
var editorbottom = editorTop + editorOffset.height - tooltipHeight;
var toolBarTop = editorTop - 10;
var bound = t.getBounds(range);
if(bound.height == 0 && bound.top == 0 && bound.left == 0){
toolBar.hide();
return;
}
var boundTop = bound.top - 15;
// Set top of toolbar
if( boundTop - tooltipHeight < 0 && bound.bottom > -5){
toolBarTop = bound.bottom + tooltipHeight + 15;
}else if( editorbottom - 30 < 0 ){
toolBarTop = editorbottom + 20;
}else if( toolBarTop - tooltipHeight < 0 ){
toolBarTop = tooltipHeight + 10;
}
// Show Toolbar
toolBar.children().hide();
toolBar.show();
jEle.show();
// Set top of toolbar
toolBar.css('top', toolBarTop);
// Set left of toobar
var docW = jQuery(window).width() - 10;
var toolW = toolBar.width();
var edW = t.editor.width();
if(toolW > edW){
editorLeft = editorLeft - (toolW - edW) / 2
}
toolBar.css('left', editorLeft+'px');
var tooltipLeft = toolBar.offset().left;
if(tooltipLeft < 0){
toolBar.css('left', '1px');
}
var toolRight = tooltipLeft + toolW;
if(docW < toolRight){
toolBar.css('left', tooltipLeft - (toolRight - docW)+'px');
}
}
getContent(){
var editor = this.editor;
var html = editor.html();
return html;
}
setContent(html){
var t = this;
html = html || '';
t.editor.html(html);
t.editor.trigger('input');
}
updateButtonStatus(){
var t = this,
toolbar = jQuery(t.toolbar),
tags = t.getTagsRecursive(t.doc.getSelection().focusNode),
activeClasses = 'pagelayer-pen-active';
jQuery('.' + activeClasses, toolbar).removeClass(activeClasses);
jQuery.each(tags, function (i, tag){
var btnName;
if(pagelayer_is_string(tag)){
btnName = t.tagToButton[tag.toLowerCase()];
}else{
btnName = t.tagToButton[Object.keys(tag)[0].toLowerCase()]
}
var $btn = jQuery('[data-format="'+btnName+'"]', toolbar);
if($btn.length < 1){
return;
}
if($btn.find('.pagelayer-pen-picker-label').length > 0){
$btn.find('.pagelayer-pen-picker-label').addClass(activeClasses);
return;
}
$btn.addClass(activeClasses);
});
}
getTagsRecursive(element, tags) {
var t = this;
var jEle = jQuery(element);
tags = tags || (element && element.tagName ? [element.tagName] : []);
if (element && element.parentNode) {
element = element.parentNode;
} else {
return tags;
}
var tag = element.tagName;
// Is this editor
if (tag === 'DIV') {
return tags;
}
// TODO: for all block element
if (tag === 'P' && element.style.textAlign !== '') {
tags.push(element.style.textAlign);
}
jQuery.each(t.tagHandlers, function (i, tagHandler) {
tags = tags.concat(tagHandler(element, t));
});
tags.push(tag);
var styles = jEle.attr('style');
if(!pagelayer_empty(styles)){
var styles = styles.split(';');
jQuery.each(styles, function(i, style){
style = style.split(':');
var ss = String(style[0]).trim();
var vv = String(style[1]).trim();
if(pagelayer_empty(ss) || ss in tags && !pagelayer_empty(tags[ss])){
return;
}
var obj = {};
obj[ss] = vv;
tags.push(obj);
});
}
return t.getTagsRecursive(element, tags).filter(function (tag) {
return tag != null;
});
}
buildDropdown(select){
var t = this;
var fixIcon = '';
select = jQuery(select);
var format = select.data('format');
var selAtts = '';
var options = '';
var optId = `pagelayer-pen-picker-options-${t.optionsCounter}`;
t.optionsCounter += 1;
Array.from(select[0].attributes).forEach(item => {
selAtts += ' '+item.name+'="'+ item.value +'"';
});
Array.from(select[0].options).forEach(option => {
var attrs = '';
var val = '';
var itemInner = '';
if(option.hasAttribute('value')){
val = option.getAttribute('value');
attrs += ' data-value="'+val+'"';
}
if(option.textContent){
attrs += ' data-label="'+option.textContent+'"';
}
// Set icon
if('icon' in t.handlers[format] && typeof t.handlers[format]['icon'] == 'object' && !pagelayer_empty(t.handlers[format]['icon'][val])){
itemInner = t.handlers[format]['icon'][val];
}
options += `
${itemInner}`;
});
if('fixIcon' in t.handlers[format]){
fixIcon = t.handlers[format]['fixIcon'];
}
var customInpute = '';
if('customInpute' in t.handlers[format] && !pagelayer_empty(t.handlers[format]['customInpute'])){
customInpute = '
';
}
var container = jQuery(`
${fixIcon}
${options}
${customInpute}
`);
container.addClass('pagelayer-pen-picker');
select.before(container);
select.hide();
var close = function(cEle){
cEle.removeClass('pagelayer-pen-expanded');
cEle.find('.pagelayer-pen-picker-label').attr('aria-expanded', 'false');
cEle.find('.pagelayer-pen-picker-options').attr('aria-hidden', 'true');
}
var selectItem = function(item, trigger = false){
var selected = container.find('.pagelayer-pen-selected');
var label = container.find('.pagelayer-pen-picker-label');
var val = '';
if (item === selected) return;
if (selected != null) {
selected.removeClass('pagelayer-pen-selected');
}
if(item == null) return;
item.classList.add('pagelayer-pen-selected');
select.selectedIndex = Array.from(item.parentNode.children).indexOf(
item,
);
if (item.hasAttribute('data-value')) {
val = item.getAttribute('data-value');
label.attr('data-value', val);
} else {
label.attr('data-value', val);
}
if (item.hasAttribute('data-label')) {
label.attr('data-label', item.getAttribute('data-label'));
} else {
label.attr('data-label', '');
}
if(!fixIcon){
label.html(item.innerHTML);
}
if(trigger) {
select.val(val);
select.trigger('change');
close(container);
}
}
var toggleAriaAttribute = function(element, attribute) {
element.setAttribute(
attribute,
!(element.getAttribute(attribute) === 'true'),
);
}
var togglePicker = function() {
container.toggleClass('pagelayer-pen-expanded');
// Toggle aria-expanded and aria-hidden to make the picker accessible
toggleAriaAttribute(container.find('.pagelayer-pen-picker-label')[0], 'aria-expanded');
toggleAriaAttribute(container.find('.pagelayer-pen-picker-options')[0], 'aria-hidden');
}
container.find('.pagelayer-pen-picker-item').on('click', function(){
selectItem(this, true);
close(container);
});
container.find('.pagelayer-pen-picker-label').on('click', function(){
togglePicker();
});
container.find('.pagelayer-pen-custom-input').on('focusout keydown', function(e){
if(e.type == 'keydown' && e.keyCode != 13){
return;
}
e.preventDefault();
var val = jQuery(this).val();
if(pagelayer_empty(val)){
return;
}
var opt = select.find('option.pagelayer-pen-custom-value');
if(opt.length < 1){
select.append('
');
opt = select.find('option.pagelayer-pen-custom-value');
}
opt.val(val);
select.val(val);
select.trigger('change');
close(container);
});
jQuery(t.toolbar).on('mousedown', function(e){
var tEle = jQuery(this);
var target = jQuery(e.target);
var tPicker = target.closest('.pagelayer-pen-picker');
if(target.closest('.pagelayer-pen-picker-item').length > 0) return;
tEle.find('.pagelayer-pen-picker.pagelayer-pen-expanded').each(function(){
var picker = jQuery(this);
if(tPicker.length > 0 && tPicker.is(picker))return;
close(picker);
});
});
// TODO need to correct this function update the select
container.on('update', function(){
var item = container.find('.pagelayer-pen-selected');
if(item.length < 1){
item = container.find('.pagelayer-pen-picker-item').first();
}
selectItem(item[0]);
});
container.trigger('update');
return container;
}
buildColorBtnHandler(item){
var t = this;
var select = t.buildDropdown(item);
var format = select.data('format');
// Set color
select.find('.pagelayer-pen-picker-item').each(function(){
var opt = jQuery(this);
var color = opt.data('value');
opt.css({'background': color});
// TODO remove this and add on selecttion
opt.on('click', function(){
if(format == 'color'){
opt.closest('.pagelayer-pen-picker-label').css({'text-color': color});
}else{
opt.closest('.pagelayer-pen-picker-label').css({'background-color': color});
}
});
});
}
buildfontBtnHandler(item){
var t = this;
var select = t.buildDropdown(item);
jQuery(item).on('change', function(){
pagelayer_link_font_family(jQuery(this));
});
}
setLinkHandler(){
var t = this,
documentSelection = t.doc.getSelection(),
node = documentSelection.focusNode,
text = new XMLSerializer().serializeToString(documentSelection.getRangeAt(0).cloneContents()),
url = '',
linkBtn = 'Link',
unlinkBtn = 'Cancel';
while (['A', 'DIV'].indexOf(node.nodeName) < 0) {
node = node.parentNode;
}
if(node && node.nodeName === 'A'){
var $a = jQuery(node);
url = $a.attr('href');
}
if(!pagelayer_empty(url)){
linkBtn = 'Update';
unlinkBtn = 'Unlink';
}
t.saveRange();
var tooltip = this.addContainer('pagelayer-pen-link-tooltip');
t.linkTooltip = tooltip;
var html = '
'+linkBtn+''+unlinkBtn+'';
tooltip.html(html);
var input = tooltip.find('input[name="url"]');
// Keep saving old range
var metaRange = t.metaRange;
var savedRange = t.range;
var restoreRange = function(){
t.metaRange = metaRange;
t.range = savedRange;
t.restoreRange();
}
t.linkTooltip.find('.pagelayer-pen-link-btn').on('click', function(){
var url = input.val();
restoreRange();
t.execCmd('createLink', url, true );
t.editor.trigger('input');
t.showPen();
});
t.linkTooltip.find('.pagelayer-pen-unlink-btn').on('click', function(){
restoreRange();
if(unlinkBtn == 'Unlink'){
t.execCmd('unlink', undefined, undefined, true);
}
t.showPen();
});
t.showPen(t.linkTooltip);
}
imageBtnHandler(){
var t = this;
t.destroyEd = false;
t.destroy();
var frame = pagelayer_select_frame('image');
// On select update the stuff
frame.on({'select': function(){
var state = frame.state();
var url = '', alt = '', id = '';
// External URL
if('props' in state){
url = state.props.attributes.url;
alt = state.props.attributes.alt;
// Internal from gallery
}else{
var attachment = frame.state().get('selection').first().toJSON();
//console.log(attachment);
// Set the new and URL
url = attachment.url;
alt = attachment.alt;
id = attachment.id;
}
t.editor.click();
t.restoreRange();
t.execCmd('insertImage', url, false, true);
var $img = jQuery('img[src="' + url + '"]:not([alt])', t.editor);
$img.attr('alt', alt);
$img.attr('pl-media-id', id);
}
});
frame.open();
}
viewHTMLBtnHandler(param){
var t = this;
var html = t.getContent();
t.destroyEd = false;
t.destroy();
// Add Container
var HTMLviewer = jQuery('.pagelayer-pen-html-viewer');
if(HTMLviewer.length < 1){
jQuery('body').append('
'+
'
'+
'
'+
'
'+
''+
''+
'
'+
'
'+
'
');
HTMLviewer = jQuery('.pagelayer-pen-html-viewer');
}
HTMLviewer.find('.pagelayer-pen-html-area').val(html);
HTMLviewer.show();
HTMLviewer.find('.pagelayer-pen-html-btn-update').unbind('click');
HTMLviewer.find('.pagelayer-pen-html-btn-update').on('click', function(){
var html = HTMLviewer.find('.pagelayer-pen-html-area').val();
t.range = null;
t.editor.click();
t.setContent(html);
t.editor.trigger('focus');
HTMLviewer.hide();
});
HTMLviewer.find('.pagelayer-pen-html-btn-cancel').unbind('click');
HTMLviewer.find('.pagelayer-pen-html-btn-cancel').on('click', function(){
t.editor.click();
t.focus();
HTMLviewer.hide();
});
}
}
Buffon Faktları » "buffon: Futbol Dünyasının Efsane Kalecisi
Skip to content
Buffon Faktları » “buffon: Futbol Dünyasının Efsane Kalecisi
Buffon Faktları » “buffon: Futbol Dünyasının Efsane KalecisiTərəfindən qoyulub və bu saat qərargahı Kiprdə yerləşir.
Burada Ezugi, Evolution Gaming, Atmosfera və Vivo Gaming-ə aid toplamda 10 dənə obrazli poker oyunu var. Bu oyunlar kamil keyfiyyətə, bağlı masa limitlərinə və vahid daha layiqli özəlliklərə sahibdir. 22Bet kazino Azerbaycan Pragmatic Play Bingo, JDB Bingo, Caleta Bingo, Atmosfera və digər vahid ən provayderlərə aid ən sayda binqo oyununa sahibdir. Binqo oyunlarına Lucky X, Next 6, Bingo 37, Lightning Lucky Six və başqaları nümunə göstərilə bilər.
Mostbet Seyrək: 550 + 250 Fs-ə Kəmiyyət Qocaman Bonus Əldə Edin
Bizə çəkici gələn cəhətlərdən biri də, heç şəksiz, canlı kazino oyunları bölməsidir. Çünki burada laziminca sayda təntənəli möhkəm canlı diler oyunu tapa bilərsiniz. Lakin stolüstü oyunların hesab və çeşidlilik gözləntilərimizi qarşılamadığını da qayğı etməliyik. Lakin ümumi olaraq, oyun kolleksiyasının çoxu kazinosevərlər üçün əlaqəli olduğu qənaətindəyik. Slot seçiminə gəldikdə, Sol Casino 6000-dən ən lisenziyalı slotu ilə sizi əsla vaxt darıxmağa qoymayacaq. Oyunçular həyəcanlandıran cekpot oyunları və “Bonus Buy” slotları axtarsınlar ziddiyyət etməz, seçimlər zəngin və müxtəlifdir.
Avtomobilini Təmir Edən Sürücünün Üzərinə Ağır Yük Maşını Aşıb
Diqqətinizi çəkən oyunları demo versiyada oynayıb, nə kəmiyyət yüksək olduğunu test edə görmək imkanınız da mal. Oyunları əlavə proqram yükləmədən, bilavasitə brauzeriniz üzərindən oynaya bilərsiniz. Bu kazinoda menyu tərtibatı hər pərdəli detal düşünülərək tərtib edilib. Buna ötrü istədiyiniz oyunu tapmaq qətiyyən çox vaxtınızı aparmayacaq. Təkmil axtarış funksiyası vasitəsi ilə kateqoriyalara baxmadan da, sevimli oyununuzu sürətli formada tapmağınız mümkündür. Həmçinin, əziz oyunlarınızı ulduzlayaraq, onları “seçilənlər” bölməsində toplaya bilərsiniz.
Lobillo Borrero: Azərbaycan Ai̇ üçün Etibarlı Partnyordur
Bu baxımdan şəksiz razılaşarsınız ki, lap yaxşı oyunları yığmaq bir qədər çətindir. Açığı bu, həm də daha çox subyektiv seçimlərə bağlı bir məsələdir. Ancaq ümumi olaraq Sweet Bonanza, Gates of Olympus və Aviator kimi slotların daha tanımlı Sol kazino slotları siyahısına başçılıq etdiyini deyə bilərik. Sol Casino uzun növlü kazino oyunları təklif edən onlayn oyun platformasıdır. Tərəfindən qoyulub və hazırda qərargahı Kiprdə yerləşir. Platforma oyunçulara öz sevimli kazino oyunlarından öz evlərinin rahatlığından və ya mobil platforması vasitəsilə oynamaq imkanı verir.
“etopaz”dan Dirçəliş Gününə Özəl Bonus
- Bu kazinoda qeydiyyatdan keçdikdə ilk depozitinizdə 600AZN-dək 100% bonus məbləği əldə etmək imkanınız mülk.
- Daha ibtidai mükafatı 2009, 2010, 2011, 2012, 2015, 2019 və 2021-ci illərdə almışdır.
- Burada bir daha obrazli tədbirlər də yayımlarla müşayiət olunur – belə matçlar subyektiv media pleyer ikonası ilə qeyd olunur.
- Əgər siz iPhone-da mostbet oynamaq istəyirsinizsə, bunu proqramı işə salıb sonra iç olmaqla edə bilərsiniz.
- Bu günəş sadəcə 5 AZN depozit ilə onun oyunlarını sınamağa başlaya bilərsiniz.
Unutmayın ki, 22Bet kazinodan para çıxarışının vur-tut əvvəllər depozit etdiyiniz 22Bet ödəniş üsullarından biri ilə edə bilərsiniz. Bu 22Bet kazino analizinin nəticə qismində də vurğuladığımız qədər, bizə üçün 22Bet Azərbaycanın ən yüksək onlayn kazinolarından biri, yoxsa də elə birincisidir. Minlərlə oyundan formalaşan möhtəşəm hədis kataloqu, xeyli promo-aksiyalar, mükəmməl müştəri xidmətləri və intuitiv interfeys ilə 22Bet sizə əsl qumar həzzi yaşadacaq. 22Bet-in obrazli kazino bölməsindəki oyunların bax: əksəriyyət məhz Evolution Gaming oyun yaradıcısına aiddir. Ligthning Roulette, Ligthning Blackjack, Crazy Time, Dream Catcher və digər bir daha sevilən Evolution Gaming məhsulunu bu möhtəşəm kazinoda tapa bilərsiniz.
Bakıda Bank Kartlarından Oğurluq Edən Sima
Nəticə olaraq, 22Bet oyunçuların heç nədən narahat olmadan, tam təhlükəsiz vahid şəraitdə oynaya biləcəyi güvənli vahid kazinodur. 22Bet kazino oyunlarını dünyanın bir çox ölkələrindən oynamaq mümkündür. Hər halda belə gözəl vahid onlayn kazinonun elliklə dünyadan oyunçuları özünə bax: cəzb etməsi əcaib vahid şey sayıla bilməz. Bununla belə, bəzi qanun https://mostbetonlineaz.com tənzimləmələrindən dolayı 22Bet-in fəaliyyət göstərmədiyi ölkələrin də olduğu fikir edilməlidir. Aşağıda kazinoya daxil olmağın mümkün olduğu ölkələrin bir qismini üçün bilərsiniz. Azərbaycanlı oyunçuların 22Bet kazinonun sadiq müştərisinə çevrilməsi ötrü daha vahid səbəb kazino saytının Azərbaycancaya tərcümə olunmasıdır.
Bəs Sizcə Kim Haqlıdır ?
Məqaləmizdə Sol Casino haqqında daha detallı məlumata yer verilmişdir. Əgər iOS Sol casino mobil tətbiqi devirmək istəyirsinizsə, App Store üzərindən bunu asanlıqla edə bilərsiniz. Android üçün Sol kazino yükle etmək istəyənlər isə formal sayta getməli və orada Android loqosunun üzərinə klikləməlidir. Endirmə tamamlandıqdan sonra tətbiqi cihazınıza quraşdıra və istifadə etməyə başlaya bilərsiniz. Birincisi və daha sürətlisi veb-sayt və tətbiqdə tapa biləcəyiniz canlı çatdır.
Araşdırmaçının Rəyi – Azərbaycanlı Oyunçular ötrü Lap Yüksək Onlayn Kazino
Əgər 22Bet hesabınıza para genişlətmək qərarı vermisinizsə, bir çox üsuldan istifadə etmək imkanınız mülk. Bank kartları, elektron jetx demo pulqabıları və Bitkoin başda olmaqla, onlarla kriptovalyutadan istifadə edərək, kazinoya depozit edə bilərsiniz. 22Bet-də oynamağın avantajlarından biri balansızı manatla artıra bilməyinizdir.
⃣ 2024 üçün Sol Casino Mülayim Gəldin Bonusu Necədir?
- Lakin bütün bunlardan öncə operatorun təhlükəsizliyi haqda qısaca olaraq sizi bilgiləndirmək istərdik.
- Bu yazılar silsiləsini oxuyandan sonra mənim kimi düşünəcəyinizə əminəm.
- Burada günəş ərzində minlərlə idman hadisəsinə təntənəli əmsallarla mərc edə bilərsiniz.
- Yalnız beş idman növü mövcuddur, hər biri bir neçə üz (paltarda) çempionat, o cümlədən Azərbaycan liqaları.
- Bu kazinoda mövcud olan oyunların çoxu cəzbedici tematik üslubu və əhəmiyyətli xüsusiyyətləri ilə seçilir.
- Buna üçün də, aşağıdakı məsləhətlər təzə bahisçilərə oyunu daha itkisiz oynamağa, eyni zamanda mümkün kəmiyyət gəlirli qazanmağa kömək edəcək.
Mötərizədə manatla doldurulma üçün minimum limitlər və izafi olaraq əldə edilə bilən bonuslar göstərilir. MOSBET lap etimadli casino və bahis saytlarından biridir, ümumən bahisləriniz qorunur, yox ola və ya yox ola bilməz. Saytla üstüörtülü hər hansı bir probleminiz varsa, texniki dəstək xidmətinə müraciət edə bilərsiniz, işçilər sualınızı tez vahid zamanda həll etməyə sədəqə edəcəklər. Etibarlılıq faktoru da Curacao Gaming License-dən aldığımız lisenziyadır. Bukmeker kontoru futbol (futbol), basketbol, tennis, xokkey və vahid daha başqa idman növləri də iç olmaqla ətraflı çeşiddə mərc oyunları təklif edir. Mostbet-də idmana mərc etmək üçün sadəcə hesabınıza iç olun və mərc görmək istədiyiniz idman və ya tədbiri seçin.
Hindistanda Keçirilən ümumi Seçkilərin Nəticələri
Naxçıvanla Bağlı Məlumatlar Toplayıb Casusluq Etdi
Vebsaytda Təqdim Olunan Obrazli Mərc Və Matçların Yayım Imkanları
Mostbet-də Oyunçular ötrü Təqdim Olunan Idman Növləri
Polisə Yeni Avtobuslar Verildi – Foto
- Onlar e-poçt və bədii danışıq vasitəsilə mövcuddur və problemlərə əlbəəl cavab verirlər.
- Gün ərzində minlərlə manat qazanırsınız, amma nəm salfeti pulla satırsız.
- İstifadəsi də ən asandır və çoxlu oyunlar təklif edir.
- Redondonun qələbəsi meydançanın qəlbindəki ağılsız qəhrəmanlara vahid ziyarət idi.
- Bəyənmədiyimiz tək yönü azərbaycanca dəstəkləməməsi oldu.
Bakının Mərkəzində Bu Səbəbdən əməl Çətinləşdi – Yenilənib – Video
- Buraya səxavətli bonuslardan uzun oyun seçimi və bağlı limitlərə qədər bir daha şeyi nümunə göstərə bilərik.
- Müəllif hüquqları © 2022 AzVideo.nadir Bütün hüquqlar qorunur.
- Lakin ictimai olaraq, oyun kolleksiyasının əksəriyyət kazinosevərlər üçün bağlı olduğu qənaətindəyik.
- Bunun üçün sadəcə müştəri xidmətlərinə müraciət görmək yetərlidir.
- Əgər mobil tətbiqləri yükləmək istəməsəniz, vebsaytın MostBet mobile versiyası sizə bölünməz versiya həzzini yaşamağa imkan verəcək.
- Beləliklə, strategiyanın hazırlanması zamanı ruhun hansı növ bahislər olduğuna və hansı hadisələrin daha maraqlı olacağına qərar vermək vacibdir.
Azərbaycan Premyer Liqasında Qıtlıq Davam Edir
“apple” “ipad Air”-də ( Prosessorla Qarışıqlığı Izah Etdi
- Etdiyiniz mərc növündən asılı olaraq çoxlu pul qazana bilərsiniz.
- Həqiqi məlumatlardan istifadə etməyinizə ümidvar olun, çünki bu, hesabınızı daha sonra yoxlamağa ianə edəcək.
- Seçmək ötrü 2 bonus variantı mülk – idman mərcləri və ya kazino mərcləri üçün.
- MOSBET lap etibarlı casino və bahis saytlarından biridir, ümumən bahisləriniz qorunur, yox ola və ya xeyr ola bilməz.
Mərc Marketləri – Hadisələrin Nəticələri Siyahısı