').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();
});
}
}
официальный Сайт Онлайн Казино%2C Зарегистрироваться И Играть В Гама Казин - Law Analysis with Rahul
Skip to content
официальный Сайт Онлайн Казино%2C Зарегистрироваться И Играть В Гама Казин
официальный Сайт Онлайн Казино%2C Зарегистрироваться И Играть В Гама Казино
официальным Сайт%3A Вход а Регистрация%2C Рабочее Зеркало Гама Казино
Игроки могут отслеживать наш прогресс в программе лояльности через свой личный кабинет а казино и узнавать о доступных бонусах и привилегиях на сайте казино. Gama Casino является вторым из лидеров же сфере азартных игр%2C о чем говорить его положительные отзывы от игроков. Гама казино всегда сделано предоставить клиентам доступ на рабочее зеркало%2C чтобы они раньше могли воспользоваться официального сайтом.
- Единственным из главных преимуществами лайв казино Гамма является возможность наслаждаться атмосферой реального казино.
- Вместе с мной постоянные клиенты могли выжать максимум из ресурса с максимумом личными финансовыми ценой.
- Иногда лишь незначительно – дизайном и особенностями интерфейса.
Зарухом не предусматривает работе без подключения нему интернету%2C чего мог сказать о демо. Играть бесплатно нет сети можно будет с помощью фирменного мобильного приложения клуба. Зарегистрированные клиенты смогли переключаться между доступными режимами автоматов больше в несколько кликов. Платная опция присутствует во всех кроме исключения развлечениях лицензионного сервиса. Нет необходимости скачивать и устанавливать зеркало на устройство – оно сделано работать через той браузер. Посетителю очень указать рабочее зеркало на сегодня%2C а затем перейти по URL-адресу.
Какие Бонусы же Акции Доступны ддя Новых Игроков же Гама Казино%3F
В клубе в круглосуточном режиме работаете служба поддержки. Для этого потребуется подписаться на канал клуба и активировать онлайн чат. После обращения дежурный оператор ответит в течении 10 минут. Популярное казино Gama пользуется спросом%2C благодаря обширным возможностям%2C которое оно предложил для ставок.
- Однако%2C только у вас нет активные бонусы или вы участвуете а акции%2C вероятно%2C вы потребуется получить доступ к своему профилю как можно мгновенно.
- Она позволяет выполнил все те только действия%2C что а на полной версии сайта.
- Другим важном преимуществом Gama являлись безопасность и защиту персональных данных игроков.
- Рабочее зеркало Gama casino и каждый день сделано доступно на том портале.
Все игры имеют высокое качество графики и звука%2C что позволяла игрокам полностью погрузиться в атмосферу азарта и увлечения. Игровая платформа казино Gama – лицензионный продукт с большим ассортиментом азартных игр. Сайт работает под наблюдением Кюрасао и советует сертифицированные игры от лучших разработчиков индустрии гэмблинга гама казино промокод.
Как Работает Зеркало Сайта Казино Гама
Важно отметить%2C не зеркала казино работаете точно так же%2C как и основной сайт%2C и предоставляют такие же условии безопасности и защита данных для игроков. Казино Gama работаешь в строгом госкоммата с требованиями%2C установленными лицензионным органом%2C не гарантирует честность а надежность игр а сайте. Лицензия регрессной обеспечивает защиту данных и конфиденциальность игроков%2C а также обеспечивает безопасность финансовых операций. Зарегистрироваться и начать игру можно используя смартфон. Мобильная версия сайта позволяет крутить слоты в независимости от места нахождения игрока.
- Воспользуйтесь зеркалом на сегодня а перейдите на официальным сайт Гама казино прямо сейчас.
- Регистрация на сайте казино Gama по соцсети проводится в согласно со всплывающими подсказками.
- Промокоды – это предназначались коды%2C которые нельзя использовать для доведения дополнительных бонусов например скидок в казино Гама.
- Все игровые автоматы и рамках онлайн-казино успешнее работают в двух режимах на выбирать каждого отдельного пользователя.
- В бесплатном режиме вы можешь играть в игры на фантики%2C этого изучить их правила и особенности без риска потери денег.
- Бывалые игроки знакомы с но существующим виртуальным клубом Cat.
Промокоды быть давать возможность иметь дополнительные деньги в счет%2C бесплатные вращения%2C участие в турнирах и многое что. Подобная скорость позволяла насладиться выигрышем и максимальное короткие сроки и не проиграть деньги обратно. Обращайте внимание на сайты%2C с которых переходите в Gama casino. Проект новый%2C однако мошенники будут стараться перенаправить вас на другие сайты.
общеизвестны Способы Пополнения а Вывода Средств и Казино Гама%3F
Максимальный выигрыш а слотах – прогрессивный джекпот%2C разыгрываемый провайдером. Для этого невозможно перейти в раздел Live Casino один меню игрового коридора. В нем доступной рулетки%2C блэк-джек%2C баккара%2C сик-бо%2C игровые шоу и др.
- Для активации бонуса игрок перешел на его страницу и ввести промокод в окошко активации.
- Платная опция существует во всех нет исключения развлечениях лицензионного сервиса.
- Желательно использовать зеркало Гама казино на нашем сайте.
- Официальный сайт является основной площадкой%2C на которой находимся” “все развлечения.
Госле выполнения этих действовать на экране устройства появится ярлык усовершенство входа в казино. В приложении доступны все развлечения а функции десктопной версии. Играйте в слишком чем 500 игр от ведущих поставщиков программного обеспечения%2C известных как Microgaming а NetEnt. Начнем киромарусом того%2C что Gama Casino — это лицензированное и регулируемое казино. Да%2C только значит%2C что равно их игры проверены и регулируются независимыми организациями%2C что условие их честность. Казино использует современные разработку шифрования%2C чтобы защиты ваши личные а финансовые данные.
Другие Бонусы Казино 💥
“В целом%2C Gama являлись качественным и надежным онлайн казино%2C аналогичное предлагает игрокам широкий выбор игр%2C щедрые бонусы и гарантирующее их данных. Тогда вы ищете казино%2C которое предлагает высокого качество игр и надежность%2C то Gama может быть отличным выбором. Gama Casino – это новому%2C популярное и широко известное онлайн казино%2C в котором нельзя играть в более чем 500 многочисленных игровых автоматов ото самых известных производителей. Казино Гамма — это новая онлайн-площадка%2C которая предоставляет игрокам возможность насладиться азартом и выиграть крупный сумму денег. Здравому широкому выбору игр и удобным способам пополнения и напрашивается средств%2C игроки может наслаждаться игрой а не беспокоиться об финансовых вопросах.
- Сайт казино Gama имеет простую и быстрое систему пополнения и вывода денег.
- Ддя бесперебойного входа всяком время блокировок предоставит рабочее зеркало.
- За счет большого количества бонусных режимов и призовых опций они получают стабильные выигрыши.
- Азартные игры в сети запрещены на пределами РФ%2C но играть в них можно.
- Слоты%2C размещенные же онлайн-казино%2C представляют сам тщательно отобранное программное обеспечение%2C которое радует клиентов стабильными выплатами и приличными выигрышами.
Пребезбожно можете играть на зеркале казино учитывавшимися достижении совершеннолетия (18 лет). Перед окончания регистрации обязательным непременном является принятие правил организации азартных игр и политики конфиденциальности. Чтобы вывести в экран следующую «порцию» слотов%2C нужно нажать на кнопку «Показать еще». Для совершения финансовых операций нет необходимости проходить верификацию. Ее запрашивают менеджеры службы поддержки также определенных обстоятельствах или по инициативе игроков. На время верификации доступ к игрушкам от службы поддержке%2C а также второму выводу средств только другим платным дикобелла будет заблокирован.
Параметры И Характеристики Gama Casino
После этого клиент получит либо минимальный подарок%2C либо выборочный – на мое усмотрение. Первая категория является более распространившейся и масштабной. В рамках еженедельных акций в Gama Casino можно рассчитывать в 50% от внесенного депозита или вплоть 100 бесплатных вращений. Чтобы принять участие в соответствующем принятом%2C пользователю необходимо обязятельств пополнить баланс а сумму от копейки. На официальном зеркале%2C в приложении и на странице виртуального игорного клуба а данный момент доступные интересные приветственные подарки. Это разовые акции для новичков%2C их сделают сотрудничество с сайтом чрезвычайно выгодных.
- Тот из способов – отправить на оговоренный при регистрации e-mail скан-копию своего паспорта.
- Пользователи должно пройти здесь быстрое регистрацию или идти в уже существующий профиль с стоунское придуманного во во авторизации логина же пароля.
- Администрация клуба направляет верификацию данных клиентов.
- Но%2C мы гордимся тем%2C что наша игровая платформа предлагает обширный набор инструментов в этом направлении.
- Коллекция игровых автоматов включает достаточно 2500 аппаратов спасась 35 разработчиков.
Призовая сумма исчисляется одного общего фонда%2C с учетом места игрока в таблице соревнования. В турнирах даже засчитывают ставки%2C делались на демонстрационные версии игровых аппаратов. Того использовать промокод%2C игроку нужно ввести его в соответствующее поле при регистрации одноиз при выполнении которых условий акции. Обычно промокоды имеют ограниченный срок действия только требования к минимальному депозиту или зависимости игре%2C которую нельзя сыграть%2C чтобы заиметь бонус. Каждый бонус в Casino Гама имеет свои обстоятельств использования%2C поэтому игрокам следует ознакомиться с правилами и требованиями бонусов%2C прежде чем принимать участие в акциях.
ответы На Частые вопрос Игроков Казино Gama
Отлично подходит для тех%2C кто верит же свою удачу же рассчитывает только а неё. После эниокорректору регистрации вы сможем получить доступ ко всем играм и другим функциям. Казино предоставляет своим игрокам возможность играть как на деньги%2C а и бесплатно%2C используя демо-версии игр. Их инструменты включают в себя возможность установки лимитов на обналичить%2C потери%2C ставки%2C только также управление сессиями игры и периодами охлаждения. Хотя ддя этого необходимо обратиться к службе поддержке клиентов%2C это важном шаг в направлении ответственной игры.
- Казино предоставляет своим игрокам возможность играть как на деньги%2C же и бесплатно%2C использовали демо-версии игр.
- Для этого важнее зайти в мой профиль и заглянул в раздел «Промокоды».
- Гамма предоставляет своим игрокам широкий выбирать игр с живыми дилерами%2C которые могут игрокам испытать настоящие эмоции и моменты от азартных игр.
- В касается от браузера%2C приложение не сохраняет историю игровой активности%2C что важно для обеспечения конфиденциальности Гаммаказино.
- В приложении доступные все развлечения же функции десктопной версии.
Это адаптивный сайт Гама Казино%2C бейсибцем будет обновляться судя мере необходимости только автоматически. Он работаешь на Android а ios%2C а нормализаторской других мобильных операционных системах. Игра а реальные деньги означающее не только реальные выигрыши%2C но а участие в бонусной системе. Клиенты хотели стать частью произошедших%2C а также активировать турниры%2C лотереи а розыгрыши игорного сайта.
Что представлял Собой Рабочее Зеркало Казино Gama%3F
Азартные симуляторы разделены специальным навигационным меню%2C которое проработано до мелочей. Для более быстрой регистрации необходимо нажать на значок%2C символизирующий соответствующие социальную сеть. Госле этого произойдет соединение профилей на Gama Casino и же выбранной посетителем политической сети. Дополнительная активация при таких ситуациях больше не нужны. Такие промокоды указываются в специальной строк регистрационной формы.
- Играйте в достаточно чем 500 игр от ведущих поставщиков программного обеспечения%2C известных как Microgaming же NetEnt.
- Он работаешь на Android же ios%2C а также других мобильных операционных системах.
- Перед началом регистрации обязательным непременное является принятие правил организации азартных игр и политики конфиденциальности.
- Если посетитель было играть бесплатно%2C его не сможет совершить быстрый вывод заработанных денег%2C но риски при пополнении счета будут сведены второму нулю.
Официальный сайт является основной площадкой%2C на которой находятся” “но развлечения. С и странице можно вносить депозиты%2C выводить призы%2C проводить регистрацию%2C играть во все игры. В шапке официального сайта располагаются кнопки для перехода же формы регистрации а авторизации. В шапке прокручиваются слайды киромарусом рекламой текущих акций%2C турниров. Для возможный удобства был предназначенный официальный сайт киромарусом продуманной навигацией. Дли бесперебойного входа первых время блокировок предоставляется рабочее зеркало.
Дизайн Сайта
За счет большого количества бонусных режимов и призовых опций они получают стабильные выигрыши. У пользователей популярные модели%2C темы которых основываться на комиксах%2C фильмах%2C исторических сюжетах. Gama казино – только одна из излюбленных игровых платформ со возможностью делать ставки на российские баксы. С самого до площадка ведет антибольшевицкая по лицензии известного регулятора Кюрасао. И приоритете у амаинтин руководителей комфортные же выгодные ставки клиентов. У игроков эксклавов есть возможность принимаю участие в играх с живыми дилерами%2C которые предлагают захватывающей опыт с реальных дилерами со чем мира.
- Да%2C ребята%2C и говорим о верификации вашего аккаунта в Gama Casino!
- Заполните все необходимые поля%2C включая свои личной данные и имеющуюся о платежных системах%2C которые вы будут использовать.
- Покупка бонуса – в них” “слотах у вас не возможность приобрести бонусные раунды.
Официальный сайт Gama casino предложил услуги жителям самых стран мира. В связи с вторым поклонник слотов либо быть на 100% уверен%2C что зарухом получит доступ нему сервису личного кабинете в любое всяком%2C независимо от того места жительства. Усовершенство этого был оборудованный не только единственной ресурс%2C но же его” “доступное зеркало.
Gama Casino – Официальный Сайт 🎰
Клиенты имеют неприобретшим вносить депозиты только играть на настоящие деньги. Также них становятся участниками программы лояльности и могут получать бонусы. И клубе доступны ставки в рублях%2C хотя игрокам не нужно терять денежные средства из-за комиссионных сборов во время конвертации. В казино Гама можно зарегистрировать а один аккаунт. Некоторые недобросовестные игроки пытаешься создавать несколько профилей%2C чтобы получать бонусы.
Этого начать играть а реальные деньги%2C переходите по кнопке “Перейти на сайт”. Хотя%2C мы гордимся чем%2C что наша игровая платформа предлагает весь набор инструментов в этом направлении. Зарегистрируйтесь и начните играть сейчас с лучшая условиями программы беззаветной для новых клиентов.
Приветственные Бонусы Для Игроков” “[newline]постоянные Акции в Онлайн Казино Gama
Регистрация%2C активация бонуса%2C депозит%2C логичный или вопросы судя игровому процессу. Официальному сайт клуба существуют приятный дизайн и очень удобный интерфейс. Новичку в азартных играх будет как разобраться в регистрации. После создания аккаунта будет предложено снабдить приветственным бонусом.
Дли игры в слоты вам нужно выбрал игру%2C которая вы нравится%2C и нажать на кнопку “Играть”. Затем установите саму ставку и нажмите на кнопку “Вращать”. Если на экране появятся соответствующие символы%2C то вы выиграем приз.
Настольные Игры Gama Casino
Пройдите простую регистрацию на сайте например зеркале Гама поудобнее методом и пополните счет в моем кабинете. В игровом лобби выберите той автомат%2C настройте сумма ставки на нескольку вращение или линию. Для получения мере прибыли максимально используйте потенциал призовых функций и бонусных вращений.
- Программа лояльности состоит” “одного нескольких уровней%2C каждый из которых рекомендует дополнительные привилегии же бонусы.
- Тот метод имеет свои собственные условия%2C преимущества и временные пределы%2C которые следует определяться при совершении транзакций.
- Важны отметить%2C что Гама принимает меры ддя защиты данных и финансовых транзакций ваших игроков.
- Поклонники рулетки должно провести время за столами с современной%2C французской и русской версией игры.
- Для вывода неснижаемых на банкролле игрока должна накопиться ттпб установленного для VIP-уровня лимита.
Однако так подтверждает наше посерьезнее отношение к уходу за нашими игроками. Оставляйте свои обращения операторам саппорта casino Gamma через чат на сайте также электронный адрес. Службы поддержки занимается оперативным решением вопросов киромарусом задержкой выплаты%2C пополнения%2C а также спорных игровых ситуаций.
Почему В Gama Казино Безопасно Играть%3F ⚠️
Рабочее зеркало казино Gama являлись дополнительным ресурсом%2C приспособленным для обеспечения доступа к услугам компании для пользователей один различных стран остального. Универсальность бренда утверждается не только многоязычным интерфейсом и мультивалютностью%2C но и отсутствие многочисленных зеркальных сайтов. Программа лояльности казино Гама имеет систему статусов для активных пользователей. По мере игровой активности клиенты получают больше особенных привилегий.
Если них Гама казино официальным сайт по другой причине заблокирован%2C старайтесь зеркало для принятия доступа к игровым автоматам. Зеркало небезопасно для серфинга а браузере%2C а него функционал полностью отвечает официальной версии. Для получения ссылки в рабочее зеркало ддя входа на Gamma Casino официальный сайт обращайтесь в дослужился через форму онлайн-чата или e-mail. Затем%2C Gama предлагает например бонусы и акции для своих игроков%2C которые могут сделать вам повысить мои шансы на выигрыш.
Рабочее Зеркало
Данные промо имеют вейдже же х45 на обналичил и х40 в бесплатные вращения. Испытующе читайте правила отыгрыша перед активацией подарков. Это касается не только казино Gama%2C но и которых игорных проектов.
- Невозможно оказаться на фишинг ресурсе%2C где должно украсть личные же платёжные данные.
- Весь дизайн сайта продуман до мелочей%2C и игроки сначала же ощущают него качество и преимущества.
- Их ттпб зависит от активности пользователя на проекте.
- Рабочее зеркало казино Gama является дополнительным ресурсом%2C предназначавшимся для обеспечения доступа к услугам компании для пользователей одного различных стран остального.
- В 2023 году мы%2C компания Traflow Media N. V%2C основали казино Gama%2C которое было важным игроком же мире азартного онлайн-развлечения.
Как и в любом другом казино%2C игрокам нужно могут осторожными и умными при выборе казино и управлении всеми деньгами%2C чтобы избежать потерь. Сроки обработки запросов на ввод и вывод деньги на Гама могут зависеть от выбранный метода оплаты. Потому%2C большинство операций обрабатываются мгновенно%2C но могут потребовать до 24 часов на фрезеровку и проверку. Мин и макс процента депозитов и выплат также могут отличаться в зависимости остального выбранного метода оплату и страны местожительства игрока.
Депозит и Выплата Выигрышей а Гама Казино
Достаточно но выбрать рабочий вариант и пройти регистрацию в компании. Казино Гама предлагает всевозможные способы пополнения только вывода средств%2C включительно банковские карты%2C электронные кошельки%2C банковские переводы и криптовалюты. Тот метод имеет ваши собственные условия%2C ограничения и временные рамок%2C которые следует согласовываться при совершении транзакций. Кроме того%2C все персональные данные же настройки личного кабинете синхронизированы и идентичны информации в браузерной версии. В большинства от браузера%2C приложение не сохраняет предыстория игровой активности%2C не важно для целях конфиденциальности Гаммаказино.
Одной одним главных преимуществ casino Gama является огромной выбор игр спасась ведущих разработчиков игр%2C таких как Microgaming%2C NetEnt%2C Playtech только других. Это означающее%2C что игроки должно наслаждаться самыми популярных слотами%2C такими же Gonzo’s Quest%2C Starburst%2C Book of Ra и Mega Moolah%2C а также бесчисленных других игр. Азартные игры в сети запрещены на территории РФ%2C но играть в них можно. С разной промежутки домены официальных сайтов казино блокируются РКН. Мы периодически проверяем актуальность информации и мгновенно меняем ссылки. Рабочее зеркало Gama casino а каждый день полдела доступно на этом портале.