1if (fQuery === undefined) { 2 fQuery = jQuery; 3} 4//font control panel plugin 5(function ($) { 6 /*global document */ 7 /*global setTimeout */ 8 /*global setInterval */ 9 /*global clearTimeout */ 10 /*global window */ 11 /*global alert */ 12 /*global prompt */ 13 /*global confirm */ 14 /*global navigator */ 15 /*global jQuery */ 16 /*global console */ 17 /*global $ */ 18 /*global ajaxproxy */ 19 /*global location */ 20 /*global tinyMCE */ 21 /*global fontBlogUrl */ 22 /*global fontBlogName */ 23 /*global clearInterval */ 24 /*global fontPluginVersion */ 25 /*global engageCompatibilityMode*/ 26 /*global ajaxproxy*/ 27 /*global ajaxproxy2*/ 28 /*global ajaxproxy3*/ 29 $.fontPlugin = function (el, options) { 30 var self = this; 31 self.$el = $(el); 32 self.el = el; 33 self.baseSelector = '#' + self.$el.attr('id'); 34 self.$el.data('fontPlugin', self); 35 //modal windows array 36 self.modals = []; 37 self.options = options; 38 self.options = $.extend({}, $.fontPlugin.defaultOptions, self.options); 39 self.version = fontPluginVersion; 40 self.settingFields = []; 41 self.effectSliders = []; 42 /* 43 Initialize 44 */ 45 self.init = function () { 46 self.detectMode(); 47 self.showLoading(); 48 self.loadSettings(); 49 if (!$.fn.on) { 50 alert('WARNING: You are using an old Wordpress version. It is not guaranteed that the plugin will work. The oldest tested Wordpress version is 3.1 but at least 3.3.1 is recommended.'); 51 } 52 // detect CSS text-shadow support in JavaScript 53 if (document.createElement("detect").style.textShadow !== "") { 54 alert('Warning: your browser does not support advanced effects and all functions of the plugin. Please upgrade to Chrome, Firefox or Internet Explorer 10'); 55 return; 56 } 57 }; 58 /* 59 * 60 * MARKUP 61 * 62 */ 63 /* 64 * Create presets panel 65 */ 66 self.createPresetsPanel = function () { 67 var i, 68 presetName, 69 presetId, 70 field, 71 paramObj, 72 upgrade, 73 modalOptions, 74 modal; 75 /* 76 PRESETS 77 */ 78 modalOptions = { 79 id: 'presetsPanel', 80 name: 'stdSettings', 81 title: self.options.compatibilityMode ? 'SAFE MODE!' : 'Font ' + self.version, 82 nobar: false, 83 left: '10px', 84 top: '50px', 85 width: '98px', 86 show: true 87 }; 88 modal = self.createNewModal(modalOptions); 89 modal.show(); 90 self.$presets = modal; 91 //add presets list 92 self.settingFields.presets = $('<fieldset id="presetsDropdownFieldset"><label>Selections<select id="presetsDropdown" name="presetsDropdown"></select></label></fieldset>'); 93 self.$presetsDropdown = self.settingFields.presets.find('select'); 94 self.$presets.append(self.settingFields.presets); 95 self.$presetsDropdown.bind('change', function () { 96 self.loadPreset($(this).val()); 97 self.scrollToSelection(); 98 }); 99 //populate presets list 100 for (i = 0; i < self.options.presets.length; i += 1) { 101 presetName = self.options.presets[i].name; 102 presetId = i; 103 self.$presetsDropdown.append('<option value="' + presetId + '">' + presetName + '</option>'); 104 } 105 // Delete current preset 106 self.settingFields.deletePreset = $('<button id="deletePreset" title="Delete">x</button>'); 107 self.settingFields.presets.append(self.settingFields.deletePreset); 108 self.settingFields.deletePreset.on('click', function () { 109 self.deleteCurrentPreset(); 110 }); 111 // Rename current preset 112 self.settingFields.renamePreset = $('<button id="renamePreset">Rename</button>'); 113 self.settingFields.presets.append(self.settingFields.renamePreset); 114 self.settingFields.renamePreset.on('click', function () { 115 self.renamePreset(); 116 }); 117 }; 118 /** 119 Like? Yes or No 120 **/ 121 self.addLikeYesNo = function () { 122 //add like not/like 123 self.$yesno = $('<div class="yesno">Like the plugin?<br><a href="http://fontsforweb.com/purchase/howtosupport?url=' + fontBlogUrl + '&name=' + fontBlogName + '" class="overlay_url yesbutton" data-upgrade="true">Yes!</a> or <a href="http://www.fontsforweb.com/contact/support" class="overlay_url nobutton">No</a></div>'); 124 self.$yesno.appendTo(self.$actions); 125 self.$yesno.css({ 126 'color': '#fff', 127 'font-size': '10px', 128 'text-align': 'right', 129 'font-weight': 'bold', 130 'float': 'left', 131 'margin-right': '10px' 132 }); 133 self.$yesno.find('a').css({ 134 'font-size': '10px', 135 'color': '#fff' 136 }); 137 }; 138 /* 139 * Create appearance panel - size and color 140 * 141 * @returns {unresolved} 142 */ 143 self.createAppearancePanel = function () { 144 var i, 145 presetName, 146 presetId, 147 field, 148 paramObj, 149 saveButton, 150 upgrade, 151 modalOptions, 152 modal, 153 settingWindows; 154 /* 155 SELECTORS 156 */ 157 //get standard fields in a new window 158 modalOptions = { 159 id: 'appearancePanel', 160 name: 'stdSettings', 161 title: 'Size and color settings', 162 left: '0', 163 top: '0px', 164 width: '100%', 165 nobar: true, 166 show: true 167 }; 168 modal = self.createNewModal(modalOptions); 169 self.$apr = modal; 170 self.$apr.hide(); 171 //create a fieldset 172 self.$standardFields = $('<div id="appearanceStandardFields"></div>').appendTo(modal); 173 //get standard fields in a new window 174 modalOptions = { 175 title: 'Extended settings', 176 left: '0', 177 top: '0' 178 }; 179 modal = self.createNewModal(modalOptions); 180 self.$extendedFields = $('<div id="appearanceExtendedFields"></div>').appendTo(modal); 181 //get extended fields not ready 182 /*var switcher = $('<a href="#" id="showExtendedFields">Load extended fields from FontsForWeb.com</a>').appendTo(self.$apr); 183 self.$extendedFields.hide(); 184 switcher.on('click', function () { self.$extendedFields.slideToggle(); self.loadExtendedFields(); return false; });*/ 185 /* 186 Add all setting fields 187 */ 188 for (i = 0; i < self.options.settingFields.length; i += 1) { 189 field = self.options.settingFields[i]; 190 paramObj = {}; 191 paramObj.field = field; 192 paramObj.type = 'lite'; 193 self.addSettingsField(paramObj); 194 } 195 //add window opening buttons 196 settingWindows = $('<fieldset id="settingsButtons"></fieldset>'); 197 //bind toggle modal 198 $('body').on('click', '.toggleModal', function () { 199 if (self.mode === 'global') { 200 var selector = self.currentPreset.selector; 201 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 202 alert('First pick an element from the page to customize it.'); 203 return; 204 } 205 } else if (self.mode === 'postPage') { 206 //VERSION FOR POST PAGE 207 //get selection 208 var selection = tinyMCE.activeEditor.selection.getContent(); 209 //only apply if something is selected 210 if (!selection) { 211 alert('Make a selection in the editor window first.'); 212 return; 213 } 214 } 215 var modalName = $(this).attr('data-modal-name'); 216 self.toggleModal(modalName); 217 }); 218 $('body').on('mousedown click', '.getApiKey', function () { 219 $(this).attr('href', 'http://fontsforweb.com/purchase?url=' + fontBlogUrl); 220 $(this).attr('target', '_blank'); 221 }); 222 //add keyup to change field 223 self.getField('selector').bind('keyup', function () { 224 $(this).trigger('change'); 225 self.hoverSelector = self.currentPreset.selector; 226 self.hoverHighlightCurrent(); 227 }); 228 }; 229 self.createActionButtons = function () { 230 var saveButton, 231 actions, 232 closeMod; 233 //add buttons fieldset 234 actions = $('<fieldset id="actionsFieldset"></fieldset>'); 235 closeMod = $('<a class="closeModal" href="#">x</a>'); 236 actions.append(closeMod); 237 self.$actions = actions; 238 closeMod.click(function () { 239 self.$presets.hide(); 240 self.$apr.hide(); 241 }); 242 //add different fields buttons 243 var fontfaceSettings = $('<button id="fontfaceSettings">Font</button>').prependTo(self.$apr); 244 //add actions 245 fontfaceSettings.on('click', function () { 246 if (self.mode === 'global') { 247 var selector = self.currentPreset.selector; 248 if (selector.indexOf('ELEMENT NOW') !== -1 || selector.indexOf('PICK ELEMENT') !== -1) { 249 alert('First pick an element from the page to customize it.'); 250 return; 251 } 252 } else if (self.mode === 'postPage') { 253 //VERSION FOR POST PAGE 254 //get selection 255 var selection = tinyMCE.activeEditor.selection.getContent(); 256 //only apply if something is selected 257 if (!selection) { 258 alert('Make a selection in the editor window first.'); 259 return; 260 } 261 } 262 self.showFontsBrowser(); 263 }); 264 // PRO settings window 265 var proSettings = $('<a href="http://fontsforweb.com/purchase/pluginupgradesubscribe?url=' + fontBlogUrl + '&name=' + fontBlogName + '" class="overlay_url" id="upgradeToProButton" data-upgrade="true">Pro settings</a>').appendTo(self.$apr); 266 // extra fields 267 var extrafieldsSettings = $('<button id="extrafieldsSettings" class="toggleModal" data-modal-name="extrafields">PRO</button>').appendTo(self.$apr); 268 // hide extra fields 269 extrafieldsSettings.hide(); 270 // effects button 271 var effects = $('<button id="effectsButton" class="toggleModal" data-modal-name="effects">Effects</button>').appendTo(self.$apr); 272 // styles button 273 var styles = $('<button id="stylesButton" class="toggleModal" data-modal-name="styles">Styles</button>').appendTo(self.$apr); 274 275 //add save button 276 saveButton = $('<button id="fontSaveSettings">Save settings</button>').appendTo(actions); 277 saveButton.click(function (e) { 278 // blink few fimes 279 saveButton.fadeTo(500, 0.3).fadeTo(500, 1).fadeTo(500, 0.3).fadeTo(500, 1).fadeTo(500, 0.3).fadeTo(500, 1).fadeTo(500, 0.3).fadeTo(500, 1).fadeTo(500, 0.3).fadeTo(500, 1); 280 //unbind click 281 saveButton.unbind('click'); 282 saveButton.css({ 283 'cursor': 'wait' 284 }); 285 self.saveSettings();
286 }); 287 self.$apr.append(actions); 288 }; 289 /* 290 * API FUNCTIONS 291 */ 292 /* 293 * check if api key is present in the database 294 */ 295 self.checkForApikey = function () { 296 self.xhrPost({ 297 url: self.options.FFW_baseUrl + '/api/getkey', 298 data: { 299 blogurl: fontBlogUrl, 300 apikey: self.options.apikey, 301 version: self.version 302 } 303 }, function (data) { 304 if (!data || data.success !== 'true') { 305 if (console !== undefined) { 306 console.log(data.message); 307 } 308 alert('An error has occured and the plugin is not working. If you\'re working on local server, make sure \n that your computer has an internet connection.'); 309 } else { 310 if(data.keytype === 'FREE' && self.loaded === true) { 311 return; 312 } 313 self.loadEffectsPanel(data.effects); 314 if (data.extended.length) { 315 self.loadExtendedFields(data.extended); 316 $('#upgradeToProButton').remove(); 317 $('#extrafieldsSettings').show(); 318 clearInterval(self.checkForApikeyInterval); 319 } 320 self.loadStylesPanel(data.styles); 321 self.options.apikey = data.apikey; 322 self.loaded = true; 323 } 324 }); 325 }; 326 //setup api key interval 327 self.setupApikeyCheckingInterval = function () { 328 if (!self.checkForApikeyInterval) { 329 self.checkForApikeyInterval = setInterval(function () { 330 self.checkForApikey(); 331 }, 5000); 332 } 333 }; 334 /* 335 * SETTINGS - SAVE AND LOAD 336 */ 337 /* 338 * Load settings from wordpress options 339 */ 340 self.loadSettings = function () { 341 var data = { 342 action: 'get_font_settings' 343 }; 344 $.ajax({
345 type: "POST", 346 url: ajaxproxy, 347 data: data, 348 success: function (response) { 349 // json is coming parsed so no $.parseJSON(response); 350 try { 351 response = $.parseJSON(response); 352 } catch (e) { 353 self.tryAnotherAjaxproxy(); 354 return; 355 } 356 //console.log(self.options); 357 if (response && response.settingFields) { 358 self.options = $.extend({}, response, self.options); 359 } else { 360 self.tryAnotherAjaxproxy(); 361 return; 362 } 363 self.loadConfig(); 364 }, 365 error: function (response) { 366 self.tryAnotherAjaxproxy(); 367 } 368 }); 369 }; 370 self.tryAnotherAjaxproxy = function () { 371 if (ajaxproxy === ajaxproxy3) { 372 alert('Sorry, but the plugin couldn\'t start. Please contact your server administrator to allow AJAX use. Power users: Use console (F12 in Chrome) to see what else could be the problem.'); 373 return; 374 } 375 else if (ajaxproxy === ajaxproxy2) { 376 ajaxproxy = ajaxproxy3; 377 } else { 378 ajaxproxy = ajaxproxy2; 379 } 380 self.loadSettings(); 381 }; 382 383 384 /** 385 * 386 * continue loading with config file 387 * 388 **/ 389 self.loadConfig = function () { 390 // try loading the plugin 391 try { 392 //console.log(self.options); 393 self.hideLoading(); 394 // markup 395 self.createPresetsPanel(); 396 self.createAppearancePanel(); 397 self.createActionButtons(); 398 self.loadPreset(0); 399 self.bindShowCategoriesAction(); 400 self.bindShowFontsAction(); 401 self.bindLinkOverlay(); 402 self.setFontOnclick(); 403 self.initUploadForm(); 404 self.adaptOptionsToMode(); 405 self.addLikeYesNo(); 406 self.checkForApikey(); 407 if (self.options.presets && self.options.presets[1]) { 408 self.loadPreset(1); 409 } 410 } catch (e) { 411 console.dir(e); 412 fQuery('#FFW_chooseFontButton, #content_FFWButton, #wp-admin-bar-font_settings > a').unbind(); 413 fQuery('#fontplugin').data('fontPlugin', false); 414 engageCompatibilityMode(function () { 415 fQuery('#wp-admin-bar-font_settings > a').trigger('click'); 416 }, e); 417 } 418 }, 419 /* 420 * Save settings by ajax 421 * 422 * @returns {unresolved} 423 */ 424 self.saveSettings = function () { 425 var savingOptions = {}, 426 data; 427 if (self.mode === 'postPage') { 428 alert('Click on "Update" or "Publish" to save'); 429 return; 430 } 431 self.$presets.hide(); 432 self.$apr.hide(); 433 self.showLoading(); 434 savingOptions.settingFields = self.options.settingFields; 435 savingOptions.presets = self.options.presets; 436 savingOptions.apikey = self.options.apikey; 437 data = { 438 action: 'set_font_settings', 439 fontPluginSettings: JSON.stringify(savingOptions) 440 }; 441 $.post(ajaxproxy, data, function (response) { 442 if (response.success !== 'true') { 443 alert('Error: ' + response.message); 444 return; 445 } else { 446 window.onbeforeunload = null; 447 location.reload(true); 448 } 449 }, 'json').error(function (xhr, textStatus, errorThrown) { 450 alert("Unknown error: \n" + xhr.responseText); 451 }); 452 }; 453 //update internal settings - value 454 self.updateSettings = function (settingName, value) { 455 if (self.mode !== 'global') { 456 return; 457 } 458 self.options.presets[self.currentPresetNo][settingName] = value; 459 }; 460 //update internal settings - css value 461 self.updateCssSettings = function (settingName, value) { 462 if (self.mode !== 'global') { 463 return; 464 } 465 self.options.presets[self.currentPresetNo].styles[settingName] = value; 466 }; 467 /* 468 update selected element CSS 469 global - update element from selector 470 postPage - update selected text 471 */ 472 self.updateSelectedElement = function (settingName, value) { 473 var selection, 474 selector, 475 selectorValid, 476 $selectorContents, 477 element, 478 node, 479 justInsertedClass, 480 newSpan, 481 newHTML, 482 inserted, 483 $tempDiv; 484 if (!value || value == 'px') return; 485 if (self.mode === 'global') { 486 //VERSION FOR GENERAL SETTINGS PAGE 487 selector = self.currentPreset.selector; 488 //exit when default selector 489 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 490 return; 491 } 492 //get the element from iframe or current page 493 if ($("#header1preview").length) { 494 element = $("#header1preview").contents().find(selector); 495 } else { 496 element = $(selector); 497 } 498 element.each(function () { 499 //CSS exceptions and general action 500 switch (settingName) { 501 case 'rotate': 502 $(this).style('-webkit-transform', 'rotate(' + value + 'deg)', 'important'); 503 $(this).style('-moz-transform', 'rotate(' + value + 'deg)', 'important'); 504 $(this).style('-o-transform', 'rotate(' + value + 'deg)', 'important'); 505 $(this).style('-ms-transform', 'rotate(' + value + 'deg)', 'important'); 506 $(this).style('transform', 'rotate(' + value + 'deg)', 'important'); 507 break; 508 //general action 509 default: 510 $(this).style(settingName, value, 'important'); 511 } 512 }); 513 } else if (self.mode === 'postPage') { 514 //VERSION FOR POST PAGE 515 //get selection 516 selection = tinyMCE.activeEditor.selection.getContent(); 517 //only apply if something is selected 518 if (!selection) { 519 return; 520 } 521 //selectorValid - validate selector created from selected text. 522 //required because for example "." with nothing following breaks function execution 523 selectorValid = true; 524 try { 525 $selectorContents = $(selection); 526 } catch (e) { 527 selectorValid = false; 528 } 529 if (selectorValid && $selectorContents.length > 1) { 530 selectorValid = false; 531 } 532 //get node 533 node = tinyMCE.activeEditor.selection.getNode(); 534 if (selectorValid && ($.trim($(node).html()) === $.trim(selection) || $.trim($(node).html()) === $.trim($(selection).html()))) { 535 //console.log('already isolated'); 536 tinyMCE.activeEditor.dom.setStyle(node, settingName, value); 537 } else { 538 //console.log('isolating: ' + $(node).html() + ' - ' + selection);
539 justInsertedClass = 'inserted' + Math.floor(Math.random() * 10000); 540 newSpan = $('<span id="' + justInsertedClass + '">' + selection + '</span>'); 541 newSpan.css(settingName, value); 542 $tempDiv = $('<div>').append(newSpan.clone()); 543 $tempDiv.find('*').each(function () { 544 //if ($(this).inlineStyle && $(this).inlineStyle(settingName)) { 545 $(this).css(settingName, value); 546 //} 547 }); 548 //get span html together with span itself 549 newHTML = $tempDiv.html(); 550 inserted = tinyMCE.activeEditor.selection.setContent(newHTML); 551 tinyMCE.activeEditor.selection.select(tinyMCE.activeEditor.dom.select('span#' + justInsertedClass)[0]); 552 } 553 } 554 }; 555 /* 556 * 557 * FIELDS 558 * 559 */ 560 /* 561 * Load extended fields 562 */ 563 self.loadExtendedFields = function (data) { 564 var i, 565 field, 566 paramObj, 567 modalOptions, 568 modal; 569 //create a new modal for it 570 modalOptions = { 571 name: 'extrafields', 572 title: 'Pro options', 573 left: '5px', 574 top: '40px', 575 width: '270px' 576 }; 577 modal = self.createNewModal(modalOptions); 578 for (i = 0; i < data.length; i += 1) { 579 field = data[i]; 580 paramObj = {}; 581 paramObj.field = field; 582 paramObj.type = 'extrafields'; 583 self.addSettingsField(paramObj); 584 } 585 self.reloadPreset(); 586 }; 587 /* 588 * Add a field to selected place 589 * paramObj 590 * 591 * @returns {unresolved} 592 * .field - field definition - no data or assignations here 593 * .settings - contain field settings 594 */ 595 self.addSettingsField = function (paramObj, loadDefaults) { 596 var field = paramObj.field, 597 thisField, 598 thisInput, 599 i, 600 manipulator, 601 fieldset, 602 fieldParam, 603 container, 604 inputFields = []; 605 if (loadDefaults === undefined) { 606 loadDefaults = false; 607 } 608 //add support for multi value field 609 if (field.settingType === 'cssmultival') { 610 if (!paramObj.target) { 611 //create a new modal for it 612 var modalOptions = { 613 name: field.name, 614 title: field.label, 615 left: '0', 616 top: '50px', 617 width: '270px' 618 }; 619 container = self.createNewModal(modalOptions); 620 } else { 621 container = paramObj.target; 622 } 623 //create a fieldset 624 fieldset = self.settingFields[field.name] = $('<fieldset id="' + field.name + 'Fieldset"></fieldset>'); 625 //add fieldset to extended fields 626 container.append(fieldset); 627 var XYSliderOptions = false; 628 //add all controls 629 for (i = 0; i < field.values.length; i += 1) { 630 fieldParam = field.values[i]; 631 var privateInputField = thisInput; 632 var subfield = fieldParam; 633 //create a field with label around 634 var manipulator = $('<label>' + subfield.label + '<a class="resetField">reset</a><input type="' + subfield.type + '" title="' + subfield.settingName + '"></label>'); 635 manipulator.appendTo(fieldset); 636 privateInputField = manipulator.find('input'); 637 privateInputField.data('fieldInfo', subfield); 638 privateInputField.data('settings', paramObj.settings); 639 // ADD CORRESPONDING ENTRY IN FIELD SETTINGS 640 if (paramObj.settings && !paramObj.settings.params) { 641 var params = {}; 642 paramObj.settings.params = params; 643 } 644 //append field to extended list 645 fieldset.append(thisField); 646 //extend field with whatever 647 privateInputField = self.extendField(privateInputField, subfield.extendWith); 648 // if handle is assigned add actions 649 if (subfield.handle) { 650 if (!XYSliderOptions) { 651 XYSliderOptions = {}; 652 XYSliderOptions.actions = []; 653 } 654 // action can be x, y, deg, distance 655 // stop - last action don't trigger input change 656 XYSliderOptions.id = privateInputField.data('settings').uniqueId; 657 inputFields[subfield.handle.linkTo] = privateInputField; 658 } 659 } 660 var XYSlider = false; 661 if (XYSliderOptions) { 662 var rand = Math.random() * 1000, 663 stop = true;
664 // if xy slider set then add it 665 XYSliderOptions.label = field.label; 666 if (field.invertX) { 667 XYSliderOptions.invertX = true; 668 } 669 XYSliderOptions.settingName = paramObj.settings.uniqueId; 670 var Mathra = Math.random(); 671 XYSliderOptions.actions = function (x, y, deg, distance) { 672 inputFields['x'] ? ( 673 inputFields['x'].val(x), 674 inputFields['x'].trigger('change', stop) 675 ) : false; 676 inputFields['y'] ? ( 677 inputFields['y'].val(y), 678 inputFields['y'].trigger('change', stop) 679 ) : false; 680 inputFields['deg'] ? ( 681 inputFields['deg'].val(deg), 682 inputFields['deg'].trigger('change', stop) 683 ) : false; 684 inputFields['distance'] ? ( 685 inputFields['distance'].val(distance / 2), 686 inputFields['distance'].trigger('change', stop) 687 ) : false; 688 }; 689 //XYSliderOptions.target = paramObj.target; 690 var $XYSlider = self.currentElement.XYSlider(XYSliderOptions); 691 XYSlider = $XYSlider.data('XYSlider'); 692 //add to effect handles 693 self.effectSliders[paramObj.settings.uniqueId] = XYSlider.$handleHolder; 694 if (!paramObj.settings.enabled) { 695 self.effectSliders[paramObj.settings.uniqueId].hide(); 696 } 697 } 698 //bind action to the inputs 699 var inputs = fieldset.find('input'); 700 //bind change to inputs 701 inputs.bind('change click keyup', function (event, stop) { 702 // settings 703 var settings = $(this).data('settings'), 704 fieldInfo = $(this).data('fieldInfo'), 705 storage = $(this).data('storage'), 706 val = $(this).val(), 707 XYSliderX, 708 XYSliderY; 709 if (stop === undefined) stop = false; 710 // add arrow up - down support 711 //37 - left, 38 - up, 39 - right, 40 - down 712 if (event.which === 38 && !isNaN(val)) { 713 $(this).val(parseFloat(val) + 1); 714 $(this).trigger('change'); 715 return false; 716 } else if (event.which === 40 && !isNaN(val)) { 717 $(this).val(parseFloat(val) - 1); 718 $(this).trigger('change'); 719 return false; 720 } 721 // save param setting 722 settings.params[fieldInfo.settingName] = val; 723 724 //console.log($(this).data('fieldInfo').settingName + ', ' + $(this).val() + ', ' + ($(this).data('fieldInfo').unit || '')) 725 //get values of all siblings and create one value for the element 726 var completeValue = ''; 727 inputs.each(function () { 728 var fieldInfo = $(this).data('fieldInfo'), 729 unit = ''; 730 if (fieldInfo.unit) { 731 unit = fieldInfo.unit; 732 } 733 //get field info 734 completeValue += ' ' + $(this).val() + unit; 735 if ($(this).val() == '') { 736 $(this).val(fieldInfo['default']); 737 } 738 if (XYSlider && !stop && fieldInfo.handle) { 739 if (fieldInfo.handle.linkTo === 'x') { 740 XYSliderX = $(this).val(); 741 } else if (fieldInfo.handle.linkTo === 'y') { 742 XYSliderY = $(this).val(); 743 } 744 } 745 }); 746 // when changing value of the input move the handle too 747 // if this input is linked to a handle 748 if (XYSlider && !stop && fieldInfo.handle) { 749 // get "linked to" of a handle and move x or y accordingly 750 if (XYSliderX && XYSliderY) {
751 XYSlider.setPosition(XYSliderX, XYSliderY); 752 } else if (XYSliderX) { 753 XYSlider.setPosition(XYSliderX, false); 754 } else if (XYSliderY) { 755 XYSlider.setPosition(false, XYSliderY); 756 } 757 } 758 // when changing value of the input move the handle too 759 // if this input is linked to a handle 760 /*if (XYSlider && !stop && fieldInfo.handle) { 761 // get "linked to" of a handle and move x or y accordingly 762 if (fieldInfo.handle.linkTo === 'x') { 763 XYSlider.setPosition($(this).val(), false); 764 } else if (fieldInfo.handle.linkTo === 'y') { 765 XYSlider.setPosition(false, $(this).val()); 766 } 767 }*/ 768 // if this is text-shadow 769 if (field.settingName === 'text-shadow') { 770 //var effect = self.getElementsEffect(settings.uniqueId); 771 completeValue = completeValue.replace(/, +$/, ''); 772 var XYSliderValues = XYSlider.getCurrentValues();
773 self.drawEffects({ 774 completeValue: completeValue, 775 target: self.currentElement, 776 color: settings.params.color, 777 x: -XYSliderValues.x, 778 y: XYSliderValues.y, 779 deg: 180 - XYSliderValues.deg * -1, 780 distance: XYSliderValues.distance, 781 effectId: settings.uniqueId, 782 effectsList: ['textShadow'] 783 }); 784 } else if (field.settingName === 'text-stroke') { 785 // go through all settings 786 //var effect = self.getElementsEffect(settings.uniqueId); 787 completeValue = completeValue.replace(/, +$/, ''); 788 //var XYSliderValues = XYSlider.getCurrentValues(); 789 self.drawEffects({ 790 target: self.currentElement, 791 color: settings.params.color, 792 distance: settings.params.width, 793 effectId: settings.uniqueId, 794 spread: settings.params.spread, 795 effectsList: ['stroke'] 796 }); 797 } else if (field.settingName === 'text-extrude') { 798 var XYSliderValues = XYSlider.getCurrentValues();
799 self.drawEffects({ 800 target: self.currentElement, 801 color: settings.params.color, 802 deg: 180 - XYSliderValues.deg * -1, 803 distance: XYSliderValues.distance, 804 effectId: settings.uniqueId, 805 effectsList: ['extrude3d'] 806 }); 807 } else if (field.settingName === 'text-extrude-shadow') { 808 var XYSliderValues = XYSlider.getCurrentValues(); 809 self.drawEffects({ 810 color: settings.params.color, 811 target: self.currentElement, 812 deg: 180 - XYSliderValues.deg * -1, 813 distance: XYSliderValues.distance, 814 effectId: settings.uniqueId, 815 effectsList: ['extrude3d', 'shadow3d'] 816 }); 817 } else if (field.settingName === 'text-shadow-multiple') { 818 var XYSliderValues = XYSlider.getCurrentValues();
819 self.drawEffects({ 820 target: self.currentElement, 821 color: settings.params.color, 822 opacity: settings.params.opacity, 823 deg: 180 - XYSliderValues.deg * -1, 824 distance: XYSliderValues.distance, 825 effectId: settings.uniqueId, 826 effectsList: ['shadow3d'] 827 }); 828 } else { 829 //console.log(field.settingName + ': ' + completeValue); 830 self.updateCssSettings(field.settingName, completeValue); 831 self.updateSelectedElement(field.settingName, completeValue); 832 } 833 return false; 834 }); 835 836 // load defaults 837 if (loadDefaults) { 838 for(var i = 0; i < inputs.length; i++) { 839 inputs.eq(i).trigger('change'); 840 } 841 // 842 inputs.eq(0).trigger('change'); 843 } 844 845 //reset field button action 846 fieldset.find('a.resetField').click(function () { 847 thisInput.val(''); 848 thisInput.trigger('change'); 849 alert('When resetting settings or deleting preset you have to save to see the change'); 850 }); 851 } else { 852 self.settingFields[field.name] = $('<fieldset id="' + field.name + 'Fieldset"><label>' + field.label + '<a class="resetField">reset</a><input type="' + field.type + '" name="' + field.name + '" title="' + field.settingName + '" id="' + field.name + 'Field"></label></fieldset>'); 853 thisField = self.settingFields[field.name]; 854 thisInput = self.getField(field.name); 855 thisInput.data('fieldInfo', field); 856 if (paramObj.target) { 857 paramObj.target.append(thisField); 858 } else if (paramObj.type === 'premium') { 859 self.$extendedFields.append(thisField); 860 } else if (paramObj.type === 'extrafields') { 861 self.modals['extrafields'].append(thisField); 862 } else { 863 if (field.name === 'selector') { 864 thisField.insertAfter('#presetsDropdownFieldset'); 865 } else { 866 self.$standardFields.append(thisField); 867 } 868 } 869 //reset field button action 870 thisField.find('a.resetField').click(function () { 871 thisInput.val(0); 872 thisInput.trigger('change'); 873 thisInput.val('none'); 874 thisInput.trigger('change'); 875 thisInput.val('inherit'); 876 thisInput.trigger('change'); 877 thisInput.val(''); 878 thisInput.trigger('change'); 879 }); 880 if (field.settingType === 'dropdown') { 881 thisInput = self.extendField(thisInput, 'dropdown'); 882 } else { 883 thisInput = self.extendField(thisInput, field.extendWith); 884 } 885 //general actions - apply settings 886 if (field.settingType === 'css' || field.settingType === 'dropdown') { 887 //bind change to color picker 888 thisInput.bind('change click keyup', function () { 889 //console.log($(this).data('fieldInfo').settingName + ', ' + $(this).val() + ', ' + ($(this).data('fieldInfo').unit || '')) 890 self.updateCssSettings($(this).data('fieldInfo').settingName, $(this).val()); 891 self.updateSelectedElement($(this).data('fieldInfo').settingName, $(this).val() + ($(this).data('fieldInfo').unit || '')); 892 return false; 893 }); 894 } else if (field.settingType === 'csstransform') { 895 //bind change to color picker 896 thisInput.bind('change click keyup', function () { 897 //console.log($(this).data('fieldInfo').settingName + ', ' + $(this).val() + ', ' + ($(this).data('fieldInfo').unit || '')) 898 self.updateCssSettings($(this).data('fieldInfo').settingName, $(this).val()); 899 self.updateSelectedElement($(this).data('fieldInfo').settingName, $(this).val() + ($(this).data('fieldInfo').unit || '')); 900 return false; 901 }); 902 } else if (field.settingType === 'general') { 903 //bind change to color picker 904 thisInput.bind('change click', function () { 905 self.updateSettings($(this).data('fieldInfo').settingName, $(this).val()); 906 self.updateSelectedElement($(this).data('fieldInfo').settingName, $(this).val()); 907 return false; 908 }); 909 } 910 } 911 }; 912 // extend field with slider, color picker etc 913 self.extendField = function (field, extendWith) { 914 if (extendWith === 'slider') { 915 var input = (function () { 916 var min = 1, 917 max = 100, 918 step = 1, 919 value = 40, 920 orientation = 'horizontal', 921 reverse = false,
922 $slider = $('<div>'), 923 input = field, 924 fieldset = input.closest('fieldset'); 925 fieldset.addClass('slider-extended'); 926 fieldset.append($slider); 927 if (input.data('fieldInfo').slider) { 928 min = parseFloat(input.data('fieldInfo').slider.min); 929 max = parseFloat(input.data('fieldInfo').slider.max); 930 step = parseFloat(input.data('fieldInfo').slider.step); 931 if (input.data('fieldInfo').slider.orientation) { 932 orientation = input.data('fieldInfo').slider.orientation; 933 } 934 if (input.data('fieldInfo').slider.value) { 935 value = input.data('fieldInfo').slider.value; 936 } 937 if (input.data('fieldInfo').slider.reverse) { 938 reverse = true; 939 } 940 } 941 //init slider 942 $slider.slider({ 943 range: "min", 944 value: value, 945 min: min, 946 max: max, 947 step: step, 948 orientation: orientation, 949 slide: function (event, ui) { 950 if (!reverse) { 951 input.val(ui.value); 952 } else { 953 //reversed values 954 input.val(max + min - ui.value); 955 } 956 input.trigger('change'); 957 } 958 }); 959 //bind value change to the size slider 960 input.bind('change click', function () { 961 var val = $(this).val(); 962 if (val) { 963 $slider.slider('value', parseFloat(val)); 964 } 965 return false; 966 }); 967 return input; 968 }()); 969 } else if (extendWith === 'dropdown') { 970 var input = (function () { 971 var $dropdown = $('<select><option></option></select>'), 972 input = field, 973 fieldset = input.parents('fieldset'), 974 key; 975 fieldset.addClass('dropdown-extended'); 976 fieldset.find('label').append($dropdown); 977 for(key in input.data('fieldInfo').dropdown) { 978 var val = input.data('fieldInfo').dropdown[key]; 979 $dropdown.append('<option value="' + key + '">' + val + '</option>'); 980 } 981 $dropdown.bind('change', function () { 982 input.val($(this).val()); 983 input.trigger('change'); 984 }); 985 //bind value change to the size slider 986 input.bind('change click', function () { 987 var val = $(this).val(); 988 if (val) { 989 $dropdown.val(val); 990 } 991 return false; 992 }); 993 return input; 994 }()); 995 } else if (extendWith === 'colorPicker') { 996 var input = (function () { 997 var input = field; 998 input.change(function () { 999 $(this).css('backgroundColor', $(this).val()); 1000 }); 1001 //init color picker 1002 input.ColorPicker({ 1003 color: '#0000ff', 1004 onShow: function (colpkr) { 1005 $(colpkr).show(); 1006 return false; 1007 }, 1008 onHide: function (colpkr) { 1009 $(colpkr).hide(); 1010 return false; 1011 }, 1012 onChange: function (hsb, hex, rgb) { 1013 input.val('#' + hex); 1014 input.trigger('change'); 1015 input.trigger('change').css('backgroundColor', '#' + hex); 1016 }, 1017 onBeforeShow: function () { 1018 $(this).ColorPickerSetColor(this.value); 1019 } 1020 }).bind('keyup', function () { 1021 $(this).ColorPickerSetColor(this.value); 1022 }); 1023 return input; 1024 }()); 1025 } else if (extendWith === 'selectorPicker') { 1026 var input = (function (field) { 1027 var replacementField, 1028 thisInput, 1029 selectorPicker, 1030 selectorPicker2, 1031 input = field, 1032 field = field.data('fieldInfo'), 1033 fieldset = input.parents('fieldset'); 1034 self.settingFields[field.name] = $('<fieldset id="selectorFieldset"><label><input type="' + field.type + '" name="' + field.name + '" title="' + field.settingName + '">CSS selecor editor (advanced)</label></fieldset>'); 1035 replacementField = self.settingFields[field.name]; 1036 thisInput = self.getField(field.name); 1037 selectorPicker = $('<button class="pickElement">Pick element</button>'); 1038 selectorPicker2 = $('<button class="pickElement pickAddElement">Pick element(add)</button>'); 1039 self.$selectorPicker = selectorPicker; 1040 self.$selectorPicker2 = selectorPicker2; 1041 // 1042 //setTimeout(function () { 1043 self.$selectorPicker.insertBefore(self.settingFields.presets); 1044 //}, 100); 1045 //replacementField.prepend(selectorPicker); 1046 replacementField.prepend(selectorPicker2); 1047 selectorPicker.on('click', function () { 1048 self.bindGetSelector(); 1049 return false; 1050 }); 1051 selectorPicker2.on('click', function () { 1052 self.bindGetSelector(true); 1053 return false; 1054 }); 1055 //replace default field 1056 fieldset.replaceWith(replacementField); 1057 replacementField.find('label').hide(); 1058 thisInput.data('fieldInfo', field); 1059 //return replaced input 1060 return thisInput; 1061 }(field)); 1062 } 1063 return input; 1064 }; 1065 // get field value 1066 self.getField = function (name) { 1067 var input = self.settingFields[name].find('input'); 1068 return input; 1069 }; 1070 // set field value 1071 self.setField = function (name, value) { 1072 var input = self.getField(name); 1073 input.val(value); 1074 input.trigger('change'); 1075 }; 1076 /* 1077 * EFFECTS 1078 */ 1079 self.loadEffectsPanel = function (data) { 1080 var i, 1081 field, 1082 paramObj, 1083 dropdown, 1084 option, 1085 field, 1086 effectsList = $('<div class="effectsList">'); 1087 // save effects to array 1088 self.effects = data; 1089 // Create effects modal 1090 var modalOptions = { 1091 id: 'effectsPanel', 1092 name: 'effects', // name conflict was here 1093 title: 'Effects', 1094 left: '50%', 1095 top: '50px', 1096 width: '190px' 1097 }; 1098 var modal = self.createNewModal(modalOptions); 1099 dropdown = $('<select>'); 1100 dropdown.append($('<option>Add new effect</option>')); 1101 // add options to the modal 1102 for (i = 0; i < data.length; i += 1) { 1103 field = data[i]; 1104 option = $('<option value="' + field.settingName + '">' + field.label + '</option>'); 1105 dropdown.append(option); 1106 } 1107 if (data.length < 3) { 1108 dropdown.append('<option value="upgrade">More options</option>'); 1109 } 1110 // add dropdown to modal 1111 modal.append(dropdown); 1112 // change 1113 dropdown.change(function () { 1114 if ($(this).val() == 'upgrade') { 1115 var link = $('<a href="http://fontsforweb.com/purchase/pluginupgradesubscribe?url=' + fontBlogUrl + '&name=' + fontBlogName + '" class="overlay_url" id="upgradeToProButton" data-upgrade="true">Pro settings</a>').appendTo('body'); 1116 link.click(); 1117 link.remove(); 1118 return; 1119 } 1120 self.addEffect($(this).val()); 1121 dropdown.find('option').eq(0).attr('selected', 'selected'); 1122 }); 1123 modal.append(effectsList); 1124 effectsList.sortable({ 1125 stop: function () { 1126 // get new order of items 1127 var items = effectsList.find('> div'), 1128 newEffectsOrder = []; 1129 // for each item 1130 items.each(function (ind) { 1131 var effectSettings = $(this).data('settings'); 1132 effectSettings.effectNo = ind; 1133 newEffectsOrder.push(effectSettings); 1134 }); 1135 self.currentPreset.effects = newEffectsOrder; 1136 // refresh text shadow effects 1137 self.updateTextShadowEffects(self.currentElement); 1138 } 1139 }); 1140 }; 1141 /* 1142 * Styles 1143 */ 1144 self.loadStylesPanel = function (data) { 1145 var i, 1146 field, 1147 paramObj, 1148 $list, 1149 field, 1150 $li, 1151 $div; 1152 // save effects to array 1153 self.styles = data; 1154 // Create styles modal 1155 var modalOptions = { 1156 id: 'stylesPanel', 1157 name: 'styles', // name conflict was here 1158 title: 'Style presets', 1159 right: '0', 1160 top: '50px', 1161 width: '400px' 1162 }; 1163 var modal = self.createNewModal(modalOptions); 1164 $list = $('<ul>'); 1165 // add dropdown to modal 1166 modal.append($list); 1167 // add options to the modal 1168 for (i = 0; i < data.length; i += 1) { 1169 field = data[i];
1170 $div = $('<div>'); 1171 $li = $('<li>').append($div) 1172 $list.append($li); 1173 1174 $div.text(field.label); 1175 $div.attr('data-value', field.settingName); 1176 1177 // create temporary preset 1178 self.createPreset(field.settingName, '[data-value="' + field.settingName + '"]'); 1179 self.loadStylePreset(field.settingName); 1180 self.unhighlightCurrent(); 1181 self.deletePreset(self.currentPresetNo, true); 1182 } 1183 if (data.length < 3) { 1184 var button = $('<button>More options</button>'); 1185 $list.append(button); 1186 button.click(function () { 1187 var link = $('<a href="http://fontsforweb.com/purchase/pluginupgradesubscribe?url=' + fontBlogUrl + '&name=' + fontBlogName + '" class="overlay_url" id="upgradeToProButton" data-upgrade="true">Pro settings</a>').appendTo('body'); 1188 link.click(); 1189 link.remove(); 1190 return; 1191 }); 1192 } 1193 1194 /*var button = $('<button>Show style</button>').appendTo(modal); 1195 button.click(function () { 1196 var i, 1197 presetSettings = {}; 1198 $.extend(true, presetSettings, self.currentPreset); 1199 delete presetSettings.name; 1200 delete presetSettings.selector; 1201 delete presetSettings.shadowEffects; 1202 delete presetSettings.styles["text-shadow"]; 1203 for(i = 0; i < presetSettings.effects.length; i++) { 1204 delete presetSettings.effects[i].calculated; 1205 } 1206 1207 alert(JSON.stringify(presetSettings)); 1208 });*/ 1209 modal.append(button); 1210 // change 1211 $list.on('click', 'li', function () { 1212 var value = $(this).find('div').data('value'); 1213 if (value === 'upgrade') { 1214 var link = $('<a href="http://fontsforweb.com/purchase/pluginupgradesubscribe?url=' + fontBlogUrl + '&name=' + fontBlogName + '" class="overlay_url" id="upgradeToProButton" data-upgrade="true">Pro settings</a>').appendTo('body'); 1215 link.click(); 1216 link.remove(); 1217 return; 1218 } else if (!value) { 1219 return; 1220 } 1221 self.loadStylePreset(value); 1222 }); 1223 }; 1224 /** 1225 * Load style from style presets 1226 **/ 1227 self.loadStylePreset = function (settingName) { 1228 var stylePreset = self.getStyleDefinitionByName(settingName), 1229 presetSettings = stylePreset.presetSettings; 1230 1231 self.unloadCurrentElementEffects(); 1232 self.currentPreset.effects = []; 1233 1234 self.populateStyles(presetSettings); 1235 1236 $.extend(true, self.currentPreset, presetSettings); 1237 self.loadEffectSettings(); 1238 self.applyFont(); 1239 self.loadFontPreview(); 1240 }; 1241 /* 1242 * load effect settings 1243 */ 1244 self.loadEffectSettings = function () { 1245 // if no effects loaded yet quit 1246 if (!self.effects) return; 1247 if (!self.currentPreset.effects) return; 1248 1249 // get effect saved settings 1250 for (var i = 0; i < self.currentPreset.effects.length; i++) { 1251 var effect = self.currentPreset.effects[i], 1252 // add effect in order to the effects list 1253 $effectItem = self.createEffectEntry(effect); 1254 if (effect.enabled) { 1255 $effectItem.find('input[name=enabled]').attr("checked", "true"); 1256 } 1257 // go through all the parameters and set them accordingly 1258 // clone object beforehand to avoid properties overwriting inside effect 1259 var params = $.extend(true, {}, effect.params); 1260 for (var property in params) { 1261 var value = params[property]; 1262 // get field from current effect 1263 var found = $effectItem.find('input[title=' + property + ']'); 1264 if (found.length) { 1265 found.val(value); 1266 found.trigger('change'); 1267 } 1268 } 1269 } 1270 }; 1271 /* 1272 * Unload current effect 1273 * 1274 * @returns {unresolved} 1275 */ 1276 self.unloadCurrentElementEffects = function () { 1277 //console.log(self.effectSliders, self.currentPreset, self.currentPreset.effects); 1278 if (self.currentPreset === undefined || self.currentPreset.effects === undefined) return; 1279 if (self.effectSliders && Object.size(self.effectSliders)) { 1280 // unload all handles 1281 for (var i = 0; i < self.currentPreset.effects.length; i++) { 1282 var effect = self.currentPreset.effects[i]; 1283 if (self.effectSliders[effect.uniqueId]) { 1284 self.effectSliders[effect.uniqueId].hide(); 1285 } 1286 } 1287 } 1288 1289 if (!self.modals['effects']) return; 1290 self.modals['effects'].find('.effectsList').html(''); 1291 }; 1292 /* 1293 * add effect to effects list 1294 */ 1295 self.addEffect = function (settingName) { 1296 var effectSettings = {}, 1297 loadDefaults = 1; 1298 if (!self.currentPreset.effects) { 1299 self.currentPreset.effects = []; 1300 effectSettings.effectNo = 0; 1301 } else { 1302 effectSettings.effectNo = self.currentPreset.effects.length; 1303 } 1304 effectSettings.settingName = settingName; 1305 effectSettings.uniqueId = effectSettings.effectNo + Math.round(Math.random() * 1000000000) + settingName; 1306 effectSettings.enabled = 1; 1307 // add effect settings to preset 1308 self.currentPreset.effects.splice(0, 0, effectSettings); 1309 // create entry
1310 return self.createEffectEntry(effectSettings, loadDefaults); 1311 }; 1312 /* 1313 * add effect to the list 1314 * 1315 * @param {type} effectId 1316 * @returns {effect} 1317 */ 1318 self.createEffectEntry = function (effectSettings, loadDefaults) { 1319 //if effects modal not created yet don't load effects 1320 if (!self.modals['effects']) return; 1321 var effectItem, 1322 effectDefinition = self.getEffectDefinitionByName(effectSettings.settingName), 1323 effectsModal = self.modals['effects'].find('.effectsList'), 1324 effectParams = $('<div class="params"></div>'), 1325 enabledCheckbox = $('<input type="checkbox" name="enabled">'), 1326 arrow = $('<a href="#" class="effectArrow"></a>'), 1327 label = $('<a href="#" class="effectName">' + effectDefinition.label + '</a>'), 1328 closeButton = $('<a href="#" class="removeEffect">x</a>'); 1329 if (loadDefaults === undefined) { 1330 loadDefaults = 0; 1331 } 1332 // create item markup 1333 effectItem = $('<div>'); 1334 effectItem.append('<div class="label">'); 1335 effectItem.find('.label').append(arrow); 1336 effectItem.find('.label').append(enabledCheckbox); 1337 effectItem.find('.label').append(label); 1338 effectItem.find('.label').append(closeButton); 1339 effectItem.append(effectParams); 1340 effectParams.hide(); 1341 if (effectSettings.enabled) { 1342 enabledCheckbox.attr('checked', 'true'); 1343 } 1344 // add settings 1345 effectsModal.prepend(effectItem); 1346 var paramObj = []; 1347 paramObj.field = effectDefinition; 1348 paramObj.settings = effectSettings; 1349 paramObj.target = effectParams; 1350 paramObj.type = 'extrafields'; 1351 1352 // actions 1353 label.click(function (e) { 1354 if (effectParams.is(':visible')) { 1355 arrow.animateRotate(0); 1356 } else { 1357 arrow.animateRotate(90); 1358 } 1359 e.preventDefault(); 1360 effectParams.slideToggle(); 1361 }); 1362 arrow.click(function (e) { 1363 if (effectParams.is(':visible')) { 1364 arrow.animateRotate(0); 1365 } else { 1366 arrow.animateRotate(90); 1367 } 1368 e.preventDefault(); 1369 effectParams.slideToggle(); 1370 }); 1371 // close button 1372 closeButton.click(function (e) { 1373 e.preventDefault(); 1374 // delete effect from 1375 self.removeEffect(effectSettings.uniqueId, effectItem); 1376 }); 1377 // enable disable checkbox 1378 enabledCheckbox.click(function (e) { 1379 if ($(this).is(':checked')) { 1380 self.enableEffect(effectSettings.uniqueId, effectItem); 1381 } else { 1382 self.disableEffect(effectSettings.uniqueId, effectItem); 1383 } 1384 }); 1385 self.addSettingsField(paramObj, loadDefaults); 1386 //add item reference in settings and settings in item 1387 //effectSettings.el = effectItem; ERROR on stringify 1388 effectItem.data('settings', effectSettings); 1389 return effectItem; 1390 }; 1391 /* 1392 * get effect definition by id 1393 */ 1394 self.getEffectDefinitionByName = function (effectId) { 1395 if (!self.effects) return false; 1396 // go thorugh all effects and find the ONE 1397 for (var i = 0; i < self.effects.length; i++) { 1398 var effect = self.effects[i]; 1399 if (effect.settingName === effectId) { 1400 return effect; 1401 } 1402 } 1403 return false; 1404 }; 1405 /* 1406 * get style 1407 */ 1408 self.getStyleDefinitionByName = function (styleId) { 1409 if (!self.styles) return false; 1410 // go thorugh all effects and find the ONE 1411 for (var i = 0; i < self.styles.length; i++) { 1412 var style = self.styles[i]; 1413 if (style.settingName === styleId) { 1414 return style; 1415 } 1416 } 1417 return false; 1418 }; 1419 /* 1420 * Enable effect 1421 * 1422 * @param {type} effectId 1423 */ 1424 self.enableEffect = function (effectId, $effectItem) { 1425 if (!self.currentPreset.effects) return false; 1426 var effect = self.getElementsEffect(effectId); 1427 effect.enabled = 1; 1428 // if has handle show it 1429 if (self.effectSliders[effectId]) { 1430 self.effectSliders[effectId].show(); 1431 } 1432 // update text shadow effects 1433 self.updateTextShadowEffects(self.currentElement); 1434 }; 1435 /* 1436 * Disable effect 1437 * 1438 * @param {type} effectId 1439 */ 1440 self.disableEffect = function (effectId, $effectItem) { 1441 if (!self.currentPreset.effects) return false; 1442 var effect = self.getElementsEffect(effectId); 1443 effect.enabled = 0; 1444 // delete shadow css 1445 self.removeShadowEffect(effectId); 1446 // if has handle hide it 1447 if (self.effectSliders[effectId]) { 1448 self.effectSliders[effectId].hide(); 1449 } 1450 }; 1451 /* 1452 * Delete effect from an element 1453 * 1454 * @param {type} effectId 1455 */ 1456 self.removeEffect = function (effectId, $effectItem) { 1457 if (!confirm('Remove the effect?')) return; 1458 if (!self.currentPreset.effects) return false; 1459 // go thorugh all effects and find the ONE 1460 for (var i = 0; i < self.currentPreset.effects.length; i++) { 1461 var effect = self.currentPreset.effects[i]; 1462 if (effect.uniqueId === effectId) { 1463 self.currentPreset.effects.splice(i, 1); 1464 } 1465 } 1466 // delete shadow css 1467 self.removeShadowEffect(effectId); 1468 if (self.effectSliders[effectId]) { 1469 // remove handle 1470 self.effectSliders[effectId].remove(); 1471 } 1472 // delete entry 1473 $effectItem.remove(); 1474 }; 1475 /* 1476 * Get effect of an element 1477 * 1478 * @param {type} effectId 1479 */ 1480 self.getElementsEffect = function (effectId) { 1481 if (!self.currentPreset.effects) return false; 1482 // go thorugh all effects and find the ONE 1483 for (var i = 0; i < self.currentPreset.effects.length; i++) { 1484 var effect = self.currentPreset.effects[i]; 1485 if (effect.uniqueId === effectId) { 1486 return effect; 1487 } 1488 } 1489 }; 1490 /* 1491 draw effects 1492 options.target; 1493 options.deg; 1494 options.distance; 1495 options.effectId; 1496 options.effectsList; 1497 */ 1498 self.drawEffects = function (options) { 1499 if (!self.shadowSupport) return false; 1500 var depth = options.distance / 10, 1501 subjectColor = options.target.css('color'), 1502 color = options.color, 1503 subjectColorRgb = self.parseRgb(subjectColor), 1504 rColor = subjectColorRgb.r, 1505 gColor = subjectColorRgb.g, 1506 bColor = subjectColorRgb.b, 1507 i = 0, 1508 j = 0, 1509 speed = i, 1510 xDist = 0, 1511 yDist = 0, 1512 //get effect 1513 effect = self.getElementsEffect(options.effectId), 1514 angle = options.deg; 1515 if (color) { 1516 var colorRgb = self.html2rgb(color.replace('#', '')); 1517 } else { 1518 colorRgb = subjectColorRgb; 1519 } 1520 // set default angle 1521 if (angle === undefined) { 1522 angle = 290; 1523 } 1524 // reset current elements calculated effect value 1525 effect.calculated = ''; 1526 // go through effects which should be applied 1527 for (i = 0; i < options.effectsList.length; i++) { 1528 depth = options.distance / 10; 1529 var effectName = options.effectsList[i]; 1530 switch (effectName) { 1531 case 'textShadow': 1532 effect.calculated += options.completeValue; 1533 //console.log(effect.calculated); 1534 //completeValue += ' ' + $(this).val() + unit; 1535 //effect.calculated = completeValue.replace(/, +$/,'') 1536 break; 1537 case 'stroke': 1538 var spread = 2; 1539 if (options.spread) { 1540 spread = options.spread; 1541 } 1542 // if distance is bigger than 4 add 1543 if (options.distance > 4) { 1544 // slash 1545 effect.calculated += options.distance + 'px ' + options.distance + 'px ' + spread + 'px ' + color + ', '; 1546 effect.calculated += -options.distance + 'px ' + options.distance + 'px ' + spread + 'px ' + color + ', '; 1547 effect.calculated += options.distance + 'px ' + -options.distance + 'px ' + spread + 'px ' + color + ', '; 1548 effect.calculated += -options.distance + 'px ' + -options.distance + 'px ' + spread + 'px ' + color + ', '; 1549 // top and down 1550 effect.calculated += options.distance + 'px 0px ' + spread + 'px ' + color + ', '; 1551 effect.calculated += -options.distance + 'px 0px ' + spread + 'px ' + color + ', '; 1552 effect.calculated += '0px ' + options.distance + 'px ' + spread + 'px ' + color + ', '; 1553 effect.calculated += '0px ' + -options.distance + 'px ' + spread + 'px ' + color + ', '; 1554 } else { 1555 // only slash 1556 effect.calculated += options.distance + 'px ' + options.distance + 'px ' + spread + 'px ' + color + ', '; 1557 effect.calculated += -options.distance + 'px ' + options.distance + 'px ' + spread + 'px ' + color + ', '; 1558 effect.calculated += options.distance + 'px ' + -options.distance + 'px ' + spread + 'px ' + color + ', '; 1559 effect.calculated += -options.distance + 'px ' + -options.distance + 'px ' + spread + 'px ' + color + ', '; 1560 } 1561 case 'extrude3d': 1562 // get color color 1563 rColor = colorRgb.r; 1564 gColor = colorRgb.g; 1565 bColor = colorRgb.b; 1566 //initially take 20% off
1567 rColor = rColor / 100 * 80, 1568 gColor = gColor / 100 * 80, 1569 bColor = bColor / 100 * 80; 1570 //loop to depth 1571 for (j = 0; j < depth; j++) { 1572 //calculate x and y of next shadow 1573 speed = 1.2; 1574 xDist += speed * Math.sin(angle * Math.PI / 180); 1575 yDist += speed * -Math.cos(angle * Math.PI / 180); 1576 xDist = xDist; 1577 yDist = yDist; 1578 //percentage darkened 1579 var percentageDone = j / depth; 1580 //darkening strength - the bigger depth the lower sstrength 1581 var light = 10 - percentageDone * 10; 1582 //darken the next shadow a bit take 10% 1583 rColor = Math.floor(rColor / 100 * 91 + light); 1584 gColor = Math.floor(gColor / 100 * 91 + light); 1585 bColor = Math.floor(bColor / 100 * 91 + light); 1586 color = 'rgb(' + rColor + ', ' + gColor + ', ' + bColor + ')'; 1587 //put together shadow setting 1588 effect.calculated += xDist.toFixed(2) + 'px ' + yDist.toFixed(2) + 'px ' + 0.3 + 'px ' + color + ', '; 1589 } 1590 break; 1591 case 'shadow3d': //generate text shadow value 1592 // get color color 1593 rColor = colorRgb.r; 1594 gColor = colorRgb.g; 1595 bColor = colorRgb.b; 1596 //loop to depth 1597 for (j = 0; j < depth; j++) { 1598 if (j > 3 && i % 3) continue; 1599 //calculate x and y of next shadow 1600 speed = 6; 1601 xDist += speed * Math.sin(angle * Math.PI / 180); 1602 yDist += speed * -Math.cos(angle * Math.PI / 180); 1603 xDist = xDist; 1604 yDist = yDist; 1605 //lighten the next shadow a bit take 10% 1606 rColor = Math.floor(rColor / 90 * 100); 1607 gColor = Math.floor(gColor / 90 * 100); 1608 bColor = Math.floor(bColor / 90 * 100); 1609 var opacity = options.opacity; 1610 if (!opacity) opacity = 0.3; 1611 color = 'rgba(' + rColor + ', ' + gColor + ', ' + bColor + ', ' + opacity + ')'; 1612 //put together shadow setting 1613 effect.calculated += xDist.toFixed(2) + 'px ' + yDist.toFixed(2) + 'px ' + ((j + 1) * 2) + 'px ' + color + ', '; 1614 } 1615 break; 1616 } 1617 } 1618 // filter result 1619 effect.calculated = effect.calculated.replace(/, +$/, ''); 1620 //apply text shadow 1621 self.updateTextShadowEffects(options.target); 1622 }; 1623 /* 1624 * Remove shadow effect 1625 * 1626 * @param {type} subject 1627 */ 1628 self.removeShadowEffect = function (effectId) { 1629 // delete from shadow effects 1630 delete self.currentPreset.shadowEffects[effectId]; 1631 // update shadow effects on given element 1632 self.updateTextShadowEffects(self.currentElement); 1633 }; 1634 //update effects 1635 self.updateTextShadowEffects = function (subject) { 1636 var allShadows = ''; 1637 // go through all currently applied 1638 for (var i = 0; i < self.currentPreset.effects.length; i++) { 1639 var effect = self.currentPreset.effects[i]; 1640 if (effect.calculated && effect.enabled) { 1641 if (allShadows) allShadows += ', '; 1642 allShadows += effect.calculated; 1643 } 1644 } 1645 if (allShadows === '') { 1646 allShadows = 'none'; 1647 } 1648 //get all different text shadows 1649 //subject[0].style.textShadow = allShadows + ' !important'; 1650 subject.each(function () { 1651 $(this).style('textShadow', allShadows, 'important'); 1652 }); 1653 self.updateCssSettings('text-shadow', allShadows); 1654 }; 1655 /* 1656 * 1657 * PRESETS MANAGEMENT 1658 * 1659 */ 1660 /* 1661 * 1662 * Create a new preset - selection 1663 * 1664 */ 1665 self.createPreset = function (presetName, selector) { 1666 var property, 1667 newPreset, 1668 newPresetId; 1669 if (selector === undefined || !selector) { 1670 selector = 'PICK AN ELEMENT NOW - or type CSS selector(advanced)'; 1671 } 1672 //get first preset as a template 1673 newPreset = {}; 1674 //set preset variables 1675 newPreset.name = presetName; 1676 newPreset.selector = selector; 1677 newPreset.fontid = ''; 1678 newPreset.fontName = ''; 1679 newPreset.effects = []; 1680 // !!! when styles are array they are not visible for PHP? 1681 newPreset.styles = {}; 1682 //reset css styles 1683 for (property in newPreset.styles) { 1684 newPreset.styles[property] = ''; 1685 } 1686 //push the preset at the end 1687 newPresetId = self.options.presets.push(newPreset) - 1; 1688 //add preset to the dropdown and select it 1689 self.$presetsDropdown.append('<option value="' + newPresetId + '">' + presetName + '</option>'); 1690 //get preset id and load it 1691 self.loadPreset(newPresetId); 1692 }; 1693 //add new preset 1694 self.renamePreset = function () { 1695 //current preset option 1696 var currPresetOption = self.$presetsDropdown.find('option[value=' + self.currentPresetNo + ']'), 1697 presetName = prompt('New preset name i.e. paragraph', currPresetOption.text()), 1698 property; 1699 if (!presetName) { 1700 return; 1701 } 1702 self.$presetsDropdown.find('option[value=' + self.currentPresetNo + ']').text(presetName); 1703 self.currentPreset.name = presetName; 1704 }; 1705 //delete preset 1706 self.deletePreset = function (presetNo, silent) { 1707 if(silent === undefined) { 1708 if (!confirm("Are you sure you want to delete this preset?")) { 1709 return false; 1710 } 1711 } 1712 if (self.options.presets.length === 1) { 1713 alert('At least one preset has to be present'); 1714 return; 1715 } 1716 if(silent === undefined) { 1717 self.unhighlightCurrent(); 1718 } 1719 self.options.presets.splice(presetNo, 1); 1720 self.$presetsDropdown.find('option[value=' + presetNo + ']').remove(); 1721 // delete all presets 1722 self.$presetsDropdown.html(''); 1723 // recreate presets menu to number values from 0 1724 for (var i = 0; i < self.options.presets.length; i += 1) { 1725 var preset = self.options.presets[i], 1726 presetName = self.options.presets[i].name, 1727 presetId = i; 1728 // unwire all outlined elements 1729 if (preset.selector.indexOf('ELEMENT NOW') === -1 && preset.selector.indexOf('PICK ELEMENT') === -1) { 1730 $(preset.selector).data('wired', false); 1731 } 1732 self.$presetsDropdown.append('<option value="' + presetId + '">' + presetName + '</option>'); 1733 } 1734 if(silent === undefined) { 1735 self.outlineAllPresets(); 1736 alert('When resetting settings or deleting preset you have to save to see the change'); 1737 self.loadPreset(0); 1738 } else if (self.options.presets && self.options.presets[1]) { 1739 self.loadPreset(1); 1740 } else { 1741 self.loadPreset(0); 1742 } 1743 }; 1744 //delete current preset 1745 self.deleteCurrentPreset = function () { 1746 self.deletePreset(self.currentPresetNo); 1747 }; 1748 /* 1749 * Reload currently loaded preset 1750 */ 1751 self.reloadPreset = function () { 1752 self.loadPreset(self.currentPresetNo); 1753 }; 1754 /* 1755 * load preset - load selection with all param values 1756 * 1757 * @param {type} presetNo 1758 * @returns {unresolved} 1759 */ 1760 self.loadPreset = function (presetNo) { 1761 var preset; 1762 presetNo = parseInt(presetNo, 10); 1763 var preset = self.options.presets[presetNo]; 1764 1765 self.unloadPreset(); 1766 if (!preset) { 1767 return; 1768 } 1769 if (self.mode === 'postPage') return; 1770 // if this is preset 0 hide appearance panel 1771 if (presetNo === 0) { 1772 self.$apr.hide(); 1773 } else { 1774 self.$apr.show(); 1775 } 1776 // if only one preset exists hide appearance panel 1777 if (self.options.presets.length == 1) { 1778 self.settingFields.presets.hide(); 1779 self.$selectorPicker2.hide(); 1780 } else { 1781 self.settingFields.presets.show(); 1782 self.$selectorPicker2.show(); 1783 } 1784 // unload effects 1785 self.unloadCurrentElementEffects(); 1786 self.currentPresetNo = presetNo; 1787 self.currentPreset = preset;
1788 // if current selector is invalid current element is false 1789 if (self.currentPreset.selector.indexOf('ELEMENT NOW') !== -1 || self.currentPreset.selector.indexOf('PICK ELEMENT') !== -1) { 1790 self.currentElement = false; 1791 } else { 1792 // otherwise get current element 1793 self.currentElement = $(self.currentPreset.selector); 1794 } 1795 // add space for shadow effects 1796 self.currentPreset.shadowEffects = []; 1797 //select preset from dropdown 1798 self.$presetsDropdown.val(presetNo); 1799 self.populateStyles(preset); 1800 self.highlightCurrent(); 1801 //load effects 1802 self.loadEffectSettings(); 1803 self.loadFontPreview(); 1804 }; 1805 self.populateStyles = function (preset) { 1806 var property, 1807 found; 1808 /* 1809 populate general fields 1810 */ 1811 for (property in preset) { 1812 found = $('body').find('input[title=' + property + ']'); 1813 if (found.length) { 1814 found.val(preset[property]); 1815 found.trigger('change'); 1816 } 1817 } 1818 /* 1819 populate css fields 1820 */ 1821 for (property in preset.styles) { 1822 found = $('body').find('input[title=' + property + ']'); 1823 if (found.length) { 1824 found.val(preset.styles[property]); 1825 found.trigger('change'); 1826 } 1827 } 1828 }; 1829 self.unloadPreset = function () { 1830 var $field, 1831 $input, 1832 $dropdown, 1833 key; 1834 // go through all fields 1835 for (key in self.settingFields) { 1836 $dropdown = []; 1837 $field = self.settingFields[key]; 1838 if (!$field || !($field instanceof $)) { 1839 continue; 1840 } 1841 $input = $field.find('input'); 1842 $input.val(''); 1843 //$input.trigger('change'); 1844 $dropdown = $field.find('select'); 1845 if ($dropdown.length) { 1846 $dropdown.val(''); 1847 $input.hide(); 1848 } 1849 } 1850 }; 1851 self.loadFontPreview = function () { 1852 var preset = self.currentPreset, 1853 imageUrl = '', 1854 originalBg = $('#fontfaceSettings').data('originalBackground'); 1855 if (preset['fontid'] && preset['fontName']) { 1856 if (!originalBg) { 1857 $('#fontfaceSettings').data('originalBackground', $('#fontfaceSettings').css('backgroundImage')); 1858 } 1859 imageUrl = self.options.FFW_baseUrl + '/public/fonts/' + preset['fontid'] + '/' + preset['fontName'] + '.png'; 1860 $('#fontfaceSettings').css({'backgroundImage': 'url(' + imageUrl + ')'}); 1861 } else if (originalBg) { 1862 $('#fontfaceSettings').css({'backgroundImage': $('#fontfaceSettings').data('originalBackground')}); 1863 } 1864 } 1865 /** 1866 * 1867 * FONTS BROWSER 1868 * 1869 */ 1870 /* 1871 Create HTML markup 1872 */ 1873 self.createFontPanel = function () { 1874 var i; 1875 var iframe = '<iframe style="width:98%; height:200px; border:none; margin: 10px 1%" frameBorder="0" src="http://fontsforweb.com/user/pluginactivate?apikey=' + self.options.apikey + '&blogurl=' + fontBlogUrl + '"></iframe>'; 1876 1877 //create html within font browser 1878 self.$el.show(); 1879 self.$el.append($('<h1 class="draggableModalBar"><a class="closeModal" href="#">x</a></h1>')); 1880 self.$el.append('<div class="tablinks"><a class="tablink" href="fontslist">Fontsforweb.com</a><a class="tablink" href="uploaded">Upload</a><a class="tablink" href="pro">PRO settings</a></div>'); 1881 self.$el.append('<div class="tab" id="fontslist"></div>'); 1882 self.$el.append('<div class="tab" id="uploaded"><div class="loading"></div></div>'); 1883 self.$el.append('<div class="tab" id="pro">' + iframe + '</div>'); 1884 1885 self.$el.find('.tab').hide(); 1886 self.$el.find('.tab').eq(0).show(); 1887 self.$el.find('.tablink').on('click', function (e) { 1888 var target, 1889 tab; 1890 e.preventDefault(); 1891 self.$el.find('.tab').hide(); 1892 target = $(this).attr('href'); 1893 tab = self.$el.find('#' + target).show(); 1894 if (target === 'uploaded') { 1895 self.loadPrivateFonts(); 1896 } 1897 return false; 1898 }); 1899 self.$el.css('left', '0') 1900 .draggable({ 1901 handle: self.$el.find('.draggableModalBar') 1902 }); 1903 $('body').on('mousedown', '.draggableModal', function () { 1904 self.modalToTop(this); 1905 }); 1906 self.$el.find('a.closeModal').on('click', function () { 1907 self.$el.hide(); 1908 return false; 1909 }); 1910 }; 1911 /* 1912 * Show fonts browser 1913 */ 1914 self.showFontsBrowser = function () { 1915 if (!this.fontInitialized) { 1916 self.createFontPanel(); 1917 self.loadFontCategories(); 1918 this.fontInitialized = true; 1919 } else {
1920 self.$el.toggle(); 1921 } 1922 self.modalToTop(self.$el); 1923 }; 1924 /* 1925 * Init fonts browser carousel 1926 */ 1927 self.initCarousel = function () { 1928 var carousel = self.$el.find('#FFW_browser_carousel').fcarousel({ 1929 buttonNextHTML: '<a href="#" onclick="return false;"></a>', 1930 buttonPrevHTML: '<a href="#" onclick="return false;"></a>', 1931 animation: 1000, 1932 scroll: 2 1933 }); 1934 }; 1935 /* 1936 * Load font categories 1937 */ 1938 self.loadFontCategories = function () { 1939 //make ajax request to get categories 1940 self.xhrPost({ 1941 url: self.options.FFW_baseUrl + '/fontcategories/fontplugininit', 1942 data: { 1943 apikey: self.options.apikey, 1944 blogurl: fontBlogUrl, 1945 ver: self.version 1946 }, 1947 format: 'html' 1948 }, 1949 function (data) { 1950 //if empty answer display error 1951 if (!data || data === '') { 1952 self.$el.html('<h1>An error has occurde</h1><p>Please try again later</p>'); 1953 } 1954 //hide loader 1955 self.$el.find('#loading').remove(); 1956 //show fonts list 1957 self.$el.find('#fontslist').html(data); 1958 //bind close to close button 1959 self.$el.find('a.close_link').on('click', function () { 1960 self.$el.toggle(); 1961 }); 1962 //init carousel 1963 self.initCarousel(); 1964 }); 1965 }; 1966 /* 1967 * bind onclick to links to reveal subcategories 1968 */ 1969 self.bindShowCategoriesAction = function () { 1970 $('body').on('click', self.baseSelector + ' #categoriesList > ul li a.categoryChoose', function () { 1971 var categoryId = $(this).attr('name'); 1972 //hide all subcategories of other parents 1973 self.$el.find('#subcategoriesList li').hide(); 1974 self.$el.find('#subcategoriesList li.instructions').show(); 1975 //show all subcategories of this parent 1976 self.$el.find('#subcategoriesList li#FFW_parentcategory_' + categoryId).show(); 1977 self.$el.find('.fcarousel-next').click(); 1978 return false; 1979 }); 1980 }; 1981 //bind onclick to reveal font of category 1982 self.bindShowFontsAction = function () { 1983 //bind onclick subcategories to load their fonts 1984 $('body').on('click', self.baseSelector + ' #subcategoriesList > ul li a.categoryChoose', function () { 1985 var categoryId = $(this).attr('name'); 1986 self.xhrPost({ 1987 url: self.options.FFW_baseUrl + '/fontcategories/wpfontsforwebcategoryfonts/catid/' + categoryId, 1988 data: { 1989 apikey: self.options.apikey, 1990 blogurl: fontBlogUrl 1991 }, 1992 format: 'html' 1993 }, 1994 function (data) { 1995 //if empty answer display error 1996 if (!data || data === '') { 1997 self.$el.html('<h1>An error has occurde</h1><p>Please reload page and try again later</p>'); 1998 } 1999 //apply content to div 2000 self.$el.find('#fontList').html(data); 2001 //move carousel right 2002 self.$el.find('.fcarousel-next').click(); 2003 }); 2004 return false; 2005 }); 2006 //bind delete function 2007 $('body').on('click', self.baseSelector + ' #uploaded a.delete', function () { 2008 if (!confirm("Are you sure you want to delete this font?")) { 2009 return false; 2010 } 2011 var fontId = $(this).attr('name'); 2012 self.xhrPost({ 2013 url: self.options.FFW_baseUrl + '/api', 2014 data: { 2015 action: 'deletefont', 2016 apikey: self.options.apikey, 2017 blogurl: fontBlogUrl, 2018 fontid: fontId 2019 } 2020 }, function (data) { 2021 if (data.success === 'true') { 2022 self.loadPrivateFonts(); 2023 } else { 2024 alert('Font deleting error.'); 2025 $('.fontUploadForm').show(); 2026 $('.fontUploading').hide(); 2027 } 2028 }); 2029 return false; 2030 }); 2031 }; 2032 /* 2033 * when clicked on font in fonts browser 2034 */ 2035 self.setFontOnclick = function () { 2036 var selector;
2037 //bind onclick font change action to font images 2038 $('body').on('click', self.baseSelector + ' #fontList a.font_pick, ' + self.baseSelector + ' .fontsList a.font_pick', function () { 2039 var element, 2040 fontName = $(this).parent().attr('title'), 2041 selector; 2042 //PAGE POST version 2043 if (self.mode === 'postPage') { //it's single post editing page 2044 //set font to id from name attribute of a 2045 self.setTinyMCEFont($(this).attr('name'), fontName); 2046 return false; 2047 } else { //GENERAL VERSION 2048 //get selector 2049 selector = self.currentPreset.selector; 2050 //exit when default selector 2051 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 2052 return; 2053 } 2054 //set form fields 2055 self.currentPreset.fontid = $(this).attr('name'); 2056 self.currentPreset.fontName = fontName; 2057 //get target element from iframe or current page 2058 if ($("#header1preview").length) { 2059 element = $("#header1preview").contents().find(); 2060 self.applyFont(element); 2061 } else { 2062 self.applyFont(); 2063 } 2064 self.loadFontPreview(); 2065 return false; 2066 } 2067 }); 2068 }; 2069 /** 2070 * apply font to selection 2071 **/ 2072 self.applyFont = function (frame) { 2073 //get selector 2074 var element, 2075 elements, 2076 fontName = self.currentPreset.fontName, 2077 selector = self.currentPreset.selector, 2078 head, 2079 linkElement; 2080 2081 if(frame === undefined) { 2082 element = $(document); 2083 head = document.getElementsByTagName('head')[0]; 2084 } else { 2085 element = frame; 2086 head = element[0].getElementsByTagName('head')[0]; 2087 } 2088 2089 linkElement = $(document.createElement('link')); 2090 //get and add stylesheet 2091 linkElement.attr({ 2092 href: self.options.FFW_baseUrl + '/font/generatepreviewcss/?id=' + self.currentPreset.fontid, 2093 rel: 'stylesheet', 2094 type: 'text/css' 2095 }); 2096 linkElement.appendTo(head); 2097 //set font family to a selector 2098 elements = element.find(selector); 2099 elements.each(function () { 2100 $(this).style("font-family", fontName, 'important'); 2101 }); 2102 } 2103 /* 2104 * Load uploaded fonts 2105 * 2106 */ 2107 self.loadPrivateFonts = function () { 2108 var apikey = self.options.apikey || false; 2109 //load private fonts 2110 self.xhrPost({ 2111 url: self.options.FFW_baseUrl + '/font/getuserfonts', 2112 data: { 2113 apikey: apikey, 2114 blogurl: fontBlogUrl, 2115 blogname: fontBlogName 2116 }, 2117 format: 'html' 2118 }, function (data) { 2119 self.$el.find('#uploaded').html(data); 2120 }); 2121 }; 2122 /* 2123 * Initialize font upload form 2124 */ 2125 self.initUploadForm = function () { 2126 $('body').on('submit', self.baseSelector + ' #fontUpload', function () { 2127 self.ajaxFontUpload.start(); 2128 }); 2129 }; 2130 /* 2131 * Upload font using ajax 2132 * 2133 */ 2134 self.ajaxFontUpload = (function () { 2135 return { 2136 start: function () { 2137 $('.fontUploadForm').hide(); 2138 $('.fontUploading').show(); 2139 $('#fontUploadIframe').load(function () { 2140 self.loadPrivateFonts(); 2141 //get info about the upload 2142 /*$.getJSON(self.options.FFW_baseUrl + '/font/wpaddsummary', function (data) { 2143 if (data.success === 'true') { 2144 self.loadPrivateFonts(); 2145 } else { 2146 alert('Font upload error. Check if file is not blocked against embedding.'); 2147 $('.fontUploadForm').show(); 2148 $('.fontUploading').hide(); 2149 } 2150 });*/ 2151 }); 2152 } 2153 }; 2154 }()); 2155 /* 2156 * 2157 * ELEMENT SELECTION AND CSS RULE GENERATION 2158 * 2159 */ 2160 /* 2161 * Enter element selection mode 2162 * 2163 * @param {type} add 2164 * @returns {unresolved} 2165 */ 2166 self.bindGetSelector = function (add) { 2167 //get selector 2168 var selector = self.currentPreset.selector; 2169 //add cancel button 2170 if (!self.$cancelSelecting) { 2171 self.$cancelSelecting = $('<a href="#" class="cancelSelecting">Stop selecting</a>'); 2172 $('body').append(self.$cancelSelecting); 2173 self.$cancelSelecting.data('cancelSelecting', true); 2174 //hide other elements 2175 self.$presets.hide(); 2176 } else { 2177 self.$cancelSelecting.show(); 2178 //hide other elements 2179 self.$presets.hide(); 2180 } 2181 $('a, button').on('click.selectionMode', function (e) { 2182 e.preventDefault(); 2183 self.handleSelectionClick($(this), add); 2184 return false; 2185 }); 2186 $('body').on('click.selectionMode', '*', function (e) { 2187 e.preventDefault(); 2188 self.handleSelectionClick($(this), add); 2189 return false; 2190 }); 2191 $('body').on('mouseover', '*', function () { 2192 if ($(this).data('cancelSelecting')) { 2193 return; 2194 } 2195 self.hoverSelector = self.getSelector(this); 2196 self.hoverHighlightCurrent(); 2197 $(this).css('outline', '3px dashed rgba(50,50,250,0.7)'); 2198 (function () { 2199 var element = $(this); 2200 setTimeout(function () { 2201 element.css('outline', 'none'); 2202 }, 100); 2203 }()); 2204 return false; 2205 }); 2206 $('body').on('mouseout', '*', function () { 2207 $(this).css('outline', 'none'); 2208 return false; 2209 }); 2210 }; 2211 /* 2212 * Enter selection mode 2213 * 2214 */
2215 self.handleSelectionClick = function ($el, add) { 2216 //if this is cancel selecting button 2217 if ($el.hasClass('cancelSelecting')) { 2218 self.stopSelectionMode(); 2219 self.reloadPreset(); 2220 return; 2221 } 2222 //if the element's preset is already created just pick it up 2223 if ($el.data('wired')) { 2224 self.$cancelSelecting.css('outline', 'none'); 2225 self.stopSelectionMode(); 2226 self.loadPreset($el.data('presetNo')); 2227 return false; 2228 } 2229 var sel = self.getSelector($el[0]), 2230 selectorInput, 2231 comma; 2232 //return false; 2233 //if not add to current preset mode 2234 if (!add) { 2235 self.stopSelectionMode(); 2236 var val = prompt('Name the selection i.e. title, header or paragraph. It\'ll be now listed in the upper left corner.'); 2237 //if not ask for new selection name 2238 if (!val) { 2239 self.bindGetSelector(add); 2240 return false; 2241 } else { 2242 //create a new preset of given selector 2243 self.createPreset(val, sel); 2244 } 2245 } 2246 self.outlineAllPresets(); 2247 selectorInput = self.getField('selector'); 2248 if (add) { 2249 comma = selectorInput.val() ? ', ' : ''; 2250 selectorInput.val(selectorInput.val() + comma + sel); 2251 } else { 2252 selectorInput.val(sel); 2253 } 2254 selectorInput.trigger('change'); 2255 self.stopSelectionMode(); 2256 self.highlightCurrent(); 2257 //load preset again to apply changes to a new element 2258 if (add) { 2259 self.reloadPreset(); 2260 } 2261 }; 2262 /* 2263 * Exit element selection mode 2264 * 2265 * @param {type} htmlcol 2266 * @returns {rgb} 2267 */ 2268 self.stopSelectionMode = function () { 2269 $('body').off('mouseover', '*'); 2270 $('body').off('click.selectionMode', '*'); 2271 $('a').off('.selectionMode'); 2272 $('button').off('.selectionMode'); 2273 $(this).css('outline', 'none'); 2274 $('body').off('mouseout', '*'); 2275 self.$cancelSelecting.hide(); 2276 //hide other elements 2277 self.$presets.show(); 2278 }; 2279 /* 2280 * Generate CSS selector for passed element 2281 * 2282 * @param {type} element 2283 * @returns {selector} 2284 */ 2285 self.getSelector = function (element) { 2286 var selector = $(element).parents() 2287 .map(function () { 2288 return this.tagName; 2289 }) 2290 .get().reverse().join(" "), 2291 id, 2292 classNames, 2293 selectorsArr, 2294 sel, 2295 parents = [], 2296 selectors = []; 2297 //go through each mapped object and get id class etc 2298 for (var i = 0; 2299 (i < $(element).parents().length && i < 4); i++) { 2300 var $parent = $(element).parents().eq(i), 2301 parentSelector = $parent[0].nodeName; 2302 //classses only for first 3 parents(now it's reversed) 2303 if (i < 2) { 2304 //get id 2305 //if (id = $parent.attr('id')) { 2306 // parentSelector += '#' + id; 2307 //} 2308 //class names 2309 classNames = $parent.attr("class"); 2310 if (classNames) { 2311 parentSelector += "." + $.trim(classNames).replace(/\s/gi, "."); 2312 } 2313 } 2314 selectors.push(parentSelector); 2315 } 2316 selector = selectors.reverse().join(' '); 2317 //get element tagname 2318 if (selector) { 2319 selector += " " + $(element)[0].nodeName; 2320 } 2321 id = $(element).attr("id"); 2322 if (id) { 2323 selector += "#" + id; 2324 } 2325 classNames = $(element).attr("class"); 2326 if (classNames) { 2327 selector += "." + $.trim(classNames).replace(/\s/gi, "."); 2328 // remove ui-draggable when re-selecting element with once removed draggability 2329 //ui-draggable 2330 } 2331 return selector; 2332 }; 2333 /* 2334 * Scroll to selected element 2335 * 2336 * @returns {unresolved} 2337 */ 2338 self.scrollToSelection = function () { 2339 var selector = self.currentPreset.selector, 2340 container, 2341 found; 2342 container = $('body'); 2343 //exit when default selector 2344 if (selector.indexOf('ELEMENT NOW') !== -1 || selector.indexOf('PICK ELEMENT') !== -1) { 2345 return; 2346 } 2347 //get by selector from the iframe 2348 found = container.find(selector); 2349 //scroll to the top when no el selected 2350 if (!found.length) { 2351 return; 2352 } 2353 //animate scroll 2354 $('html, body').animate({ 2355 scrollTop: (parseInt(found.offset().top, 10) - 150) 2356 }, 'slow'); 2357 }; 2358 /* 2359 * Highlight current element on hover 2360 */ 2361 self.hoverHighlightCurrent = function () { 2362 var selector = self.hoverSelector; 2363 if (self.tempHightlighted) { 2364 self.tempHightlighted.css('outline', 'none'); 2365 } 2366 //exit when default selector 2367 if (selector.indexOf('ELEMENT NOW') !== -1 || selector.indexOf('PICK ELEMENT') !== -1) { 2368 return; 2369 } 2370 self.tempHightlighted = $(selector); 2371 self.tempHightlighted.css('outline', '3px dashed rgba(100,250,100,0.7)'); 2372 }; 2373 /* 2374 * highlight all elements(with edititng option) 2375 */ 2376 self.outlineAllPresets = function () { 2377 //go through all presets 2378 for (var i = 0; i < self.options.presets.length; i++) { 2379 if (parseInt(i, 10) === parseInt(self.currentPresetNo, 10)) continue; 2380 var preset = self.options.presets[i]; 2381 var selector = preset.selector; 2382 //exit when default selector 2383 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 2384 continue; 2385 } 2386 var litme = $(selector); 2387 litme.css('outline', '2px dashed rgba(150,150,250,0.3)'); 2388 $('.deletePreset').remove(); 2389 litme.css("cursor", 'pointer', 'important'); 2390 if (litme.data('wired') === true) { 2391 continue; 2392 } 2393 litme.data('wired', true); 2394 (function () { 2395 var ind = i; 2396 litme.data('presetNo', ind); 2397 litme.click(function (e) { 2398 // onbeoforeunload helps here 2399 //e.preventDefault(); 2400 if (parseInt($(this).data('presetNo'), 10) !== parseInt(self.currentPresetNo, 10)) { 2401 e.preventDefault(); 2402 self.loadPreset(ind); 2403 } 2404 }); 2405 litme.hover( 2406 function () { 2407 if (parseInt($(this).data('presetNo'), 10) !== parseInt(self.currentPresetNo, 10)) { 2408 $(this).css('outline', '2px dashed rgba(150,150,250,0.9)'); 2409 } 2410 }, 2411 function () { 2412 if (parseInt($(this).data('presetNo'), 10) !== parseInt(self.currentPresetNo, 10)) { 2413 $(this).css('outline', '2px dashed rgba(150,150,250,0.3)'); 2414 } 2415 } 2416 ); 2417 }()); 2418 } 2419 }; 2420 /* 2421 * highlight current 2422 * @returns {unresolved} 2423 */ 2424 self.highlightCurrent = function () { 2425 var selector = self.currentPreset.selector, 2426 btn; 2427 self.outlineAllPresets(); 2428 //exit when default selector 2429 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 2430 return; 2431 } 2432 self.hightlighted = $(selector); 2433 self.hightlighted.css('outline', '3px dashed rgba(250,50,30,0.7)'); 2434 self.hightlighted.style("cursor", 'move', 'important'); 2435 if(!self.hightlighted.find('.deletePreset')[0]) { 2436 btn = $('<button class="deletePreset">X</button>') 2437 self.hightlighted.append(btn); 2438 btn.click(function (e) { 2439 e.preventDefault(); 2440 self.deleteCurrentPreset(); 2441 return false; 2442 }); 2443 } 2444 self.makeCurrentDraggable(); 2445 }; 2446 /* 2447 * Removes highlighting from current element 2448 * 2449 * @returns {unresolved} 2450 */ 2451 self.unhighlightCurrent = function () { 2452 var selector = self.currentPreset.selector; 2453 self.outlineAllPresets(); 2454 //exit when default selector 2455 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 2456 return; 2457 } 2458 self.hightlighted = $(selector); 2459 self.hightlighted.css('outline', 'none'); 2460 self.hightlighted.style("cursor", ''); 2461 //self.removeCurrentDraggable(); 2462 // remove draggable 2463 self.hightlighted.draggable("destroy"); 2464 }; 2465 /* 2466 * make current element draggable 2467 */ 2468 self.makeCurrentDraggable = function () { 2469 var isMozilla = $.browser && $.browser.mozilla; 2470 self.hightlighted.draggable({ 2471 drag: function (event, ui) { 2472 var top = ui.position.top, 2473 left = ui.position.left, 2474 $el = self.hightlighted; 2475 $el.each(function () { 2476 //set position to relative 2477 $(this).style("position", 'relative', 'important'); 2478 //set slider y to dragged value (parseInt(top,10) + parseInt($(window).scrollTop(),10)) 2479 //for firefox only 2480 if (isMozilla) { 2481 self.updateCssSettings('top', (parseInt(top, 10) + parseInt($(window).scrollTop(), 10)) + 'px'); 2482 } else { 2483 self.updateCssSettings('top', top + 'px'); 2484 } 2485 //set slider x to dragged value 2486 self.updateCssSettings('left', left + 'px'); 2487 //set position to relative 2488 self.updateCssSettings('position', 'relative'); 2489 }); 2490 //waiting to set top and left to "!important" after jquery ui draggable 2491 setTimeout(function () { 2492 $el.each(function () { 2493 //for firefox only 2494 if (isMozilla) { 2495 $(this).style("top", (parseInt(top, 10) + parseInt($(window).scrollTop(), 10)) + 'px', 'important'); 2496 } else { 2497 $(this).style("top", top + 'px', 'important'); 2498 } 2499 //set slider x to dragged value 2500 $(this).style("left", left + 'px', 'important'); 2501 }); 2502 }, 10); 2503 } 2504 }); 2505 }; 2506 /** 2507 * 2508 * COLOR CONVERSION FUNCTIONS 2509 * 2510 */ 2511 /* 2512 * Convert from HEX/HTML to rgb object 2513 * 2514 * @param {type} htmlcol 2515 * @returns {rgb} 2516 */ 2517 self.html2rgb = function (htmlcol) { 2518 var rgb = new Object(); 2519 rgb.r = self.html2dec(htmlcol.substr(0, 2)); 2520 rgb.g = self.html2dec(htmlcol.substr(2, 2)); 2521 rgb.b = self.html2dec(htmlcol.substr(4, 2)); 2522 return rgb; 2523 }; 2524 /* 2525 * Parse RGB to HTML to 2526 * @param {type} rgbString 2527 * @returns {@exp;self@call;html2rgb} 2528 */ 2529 self.parseRgb = function (rgbString) { 2530 return self.html2rgb(self.rgbString2hex(rgbString)); 2531 }; 2532 self.rgbString2hex = function (rgbString) { 2533 var parts = rgbString.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); 2534 // parts now should be ["rgb(0, 70, 255", "0", "70", "255"] 2535 if (!parts) return '000000'; 2536 delete(parts[0]); 2537 for (var i = 1; i <= 3; ++i) { 2538 parts[i] = parseInt(parts[i]).toString(16); 2539 if (parts[i].length == 1) parts[i] = '0' + parts[i];
2540 } 2541 var hexString = parts.join(''); 2542 return hexString; 2543 }; 2544 /* 2545 * Converts color from HEX/HTML-style (00-FF) to decimal color value (0-255) 2546 */ 2547 self.html2dec = function (h) { 2548 return parseInt(h, 16); 2549 }; 2550 /* 2551 * 2552 * MODAL WINDOWS AND OVERLAYS 2553 * 2554 */ 2555 /* 2556 * Create new modal window 2557 */ 2558 self.createNewModal = function (options) { 2559 var modal = $('<div class="draggableModal"><h1 class="draggableModalBar">' + options.title + '<a class="closeModal" href="#">x</a></h1></div>'); 2560 modal.css({ 2561 left: options.left ? options.left : 'auto', 2562 right: options.right ? options.right : 'auto', 2563 top: options.top, 2564 width: options.width, 2565 position: 'fixed', 2566 zIndex: 1000000 2567 }); 2568 if (options.nobar) { 2569 modal.find('h1.draggableModalBar').hide(); 2570 } 2571 if (!options.show) { 2572 modal.hide(); 2573 } 2574 if (options.id) { 2575 modal.attr('id', options.id); 2576 } 2577 self.modals[options.name] = modal; 2578 2579 //make draggable 2580 modal.draggable({ 2581 handle: modal.find('.draggableModalBar'), 2582 start: function () { 2583 $(this).css('bottom', 'auto'); 2584 } 2585 }); 2586 2587 modal.find('.closeModal').click(function () { 2588 modal.hide(); 2589 return; 2590 }); 2591 modal.appendTo($('body')); 2592 //self.modalToTop(modal); 2593 return modal; 2594 }; 2595 /* 2596 * create a popup with content for overlay links 2597 * 2598 * @returns {unresolved} 2599 */ 2600 self.bindLinkOverlay = function () { 2601 $('body').on('click', 'a.font_url, a.overlay_url, button.overlay_url', function () { 2602 var modal, 2603 frameSrc, 2604 iframe, 2605 overlay, 2606 href = $(this).attr('href'); 2607 if ($(this).attr('data-upgrade') === 'true') { 2608 self.setupApikeyCheckingInterval(); 2609 } 2610 //create overlay 2611 overlay = $('<div id="memberOverlay"></div>'); 2612 overlay.appendTo(document.body); 2613 overlay.css({ 2614 position: 'fixed', 2615 top: 0, 2616 left: 0, 2617 width: '100%', 2618 height: '100%', 2619 'background-color': '#333',
2620 filter: 'alpha(opacity=50)', 2621 '-moz-opacity': 0.5, 2622 '-khtml-opacity': 0.5, 2623 opacity: 0.5, 2624 'z-index': 200000001 2625 }); 2626 modal = $('<div class="draggableModal ui-draggable"><h1 class="draggableModalBar">' + href + ' <a class="closeModal" href="#">x</a></h1></div>'); 2627 modal.css({ 2628 position: 'fixed', 2629 left: '-475px', 2630 marginLeft: '50%', 2631 width: '950px', 2632 top: '40px', 2633 zIndex: 200000001 2634 }); 2635 modal.find('.closeModal').bind('mousedown', function () { 2636 modal.remove(); 2637 overlay.remove(); 2638 return; 2639 }); 2640 frameSrc = href; 2641 iframe = $('<iframe style="width:98%; height:490px; border:none; margin: 10px 1%" frameBorder="0" src="' + frameSrc + '"></iframe>'); 2642 iframe.appendTo(modal); 2643 modal.appendTo($('body')).show(); 2644 overlay.click(function () { 2645 modal.remove(); 2646 $(this).remove(); 2647 }); 2648 return false; 2649 }); 2650 return; 2651 }; 2652 /* 2653 * adapt plugin looks to different modes - global or post page 2654 */ 2655 self.adaptOptionsToMode = function () { 2656 if (self.mode === 'postPage') { 2657 self.settingFields.presets.hide(); 2658 self.$presets.hide(); 2659 self.$apr.show(); 2660 self.settingFields.selector.hide(); 2661 $('#fontSaveSettings').hide(); 2662 $('#effectsButton').hide(); 2663 } 2664 }; 2665 /* 2666 * Show hide modal 2667 * 2668 * @param {type} modalName 2669 */ 2670 self.toggleModal = function (modalName) { 2671 if (self.modals[modalName] === undefined) { 2672 return; 2673 } 2674 // if this is effects button 2675 if (modalName === 'effects') { 2676 // detect CSS text-shadow support in JavaScript 2677 if (document.createElement("detect").style.textShadow !== "") { 2678 alert('Sorry, but your browser does not support advanced effects. Please upgrade to Chrome, Firefox or Internet Explorer 10'); 2679 return; 2680 } 2681 } 2682 self.modals[modalName].toggle(); 2683 self.modalToTop(self.modals[modalName]); 2684 }; 2685 /* 2686 * Put modal on top 2687 * 2688 * @param {type} selectedModal 2689 */ 2690 self.modalToTop = function (selectedModal) { 2691 var highestZindex = 1000000; 2692 for (var index in self.modals) { 2693 var modal = self.modals[index], 2694 modalZindex = modal.css('zIndex'); 2695 if (parseInt(modalZindex, 10) > parseInt(highestZindex, 10)) { 2696 highestZindex = modalZindex; 2697 } 2698 } 2699 $(selectedModal).css({ 2700 'zIndex': parseInt(highestZindex, 10) + 1 2701 }); 2702 }; 2703 /* 2704 * 2705 * TINY MCE EDITOR 2706 * 2707 */ 2708 /* 2709 * set font for post or page in tinymce 2710 */ 2711 self.setTinyMCEFont = function (fontId, fontName) { 2712 //get selection 2713 var selection = tinyMCE.activeEditor.selection.getContent(), 2714 selectorValid, 2715 $selectorContents, 2716 fontClass, 2717 node, 2718 newSpan, 2719 newHTML, 2720 inserted, 2721 $tempDiv, 2722 multipleSelectors; 2723 //only apply if something is selected 2724 if (!selection) { 2725 return; 2726 } 2727 //get node 2728 fontClass = "fontplugin_fontid_" + fontId + "_" + fontName; 2729 node = tinyMCE.activeEditor.selection.getNode(); 2730 //selectorValid - validate selector created from selected text. 2731 //required because for example "." with nothing following breaks function execution 2732 selectorValid = true; 2733 try { 2734 $selectorContents = $(selection); 2735 } catch (e) { 2736 selectorValid = false; 2737 } 2738 if (selectorValid && $selectorContents.length > 1) { 2739 selectorValid = false; 2740 multipleSelectors = true; 2741 } 2742 if (selectorValid && ($.trim($(node).html()) === $.trim(selection) || $.trim($(node).html()) === $.trim($(selection).html()))) { 2743 //console.log('already isolated'); 2744 tinyMCE.activeEditor.dom.setAttrib(node, 'class', fontClass); 2745 } else if (multipleSelectors) { 2746 $selectorContents.each(function () {
2747 $(this).removePrefixedClasses('fontplugin_fontid_'); 2748 $(this).addClass(fontClass); 2749 2750 $(this).attr('class').split(' '); 2751 }); 2752 $tempDiv = $('<div>').append($selectorContents); 2753 newHTML = $tempDiv.html(); 2754 2755 inserted = tinyMCE.activeEditor.selection.setContent(newHTML); 2756 } else { 2757 newSpan = $("<span class=\"" + fontClass + "\">" + selection + '</span>'); 2758 //get span html together with span itself 2759 newHTML = $('<div>').append(newSpan.clone()).html(); 2760 //add font in use 2761 inserted = tinyMCE.activeEditor.selection.setContent(newHTML); 2762 tinyMCE.activeEditor.selection.select(tinyMCE.activeEditor.dom.select('span.' + fontClass)[0]); 2763 } 2764 //loads font face to iframe editor 2765 self.loadFontFace(fontId); 2766 }; 2767 /* 2768 * Load font to tinymce iframe 2769 */ 2770 self.loadFontFace = function (fontId) { 2771 var head = self.postIframe[0].getElementsByTagName('head')[0], 2772 linkElement = $(document.createElement('link')); 2773 linkElement.attr({ 2774 href: self.options.FFW_baseUrl + '/font/generatepreviewcss/?id=' + fontId, 2775 rel: 'stylesheet', 2776 type: 'text/css' 2777 }); 2778 linkElement.appendTo(head); 2779 }; 2780 /* 2781 * 2782 * UTILITY FUNCTIONS 2783 * 2784 */ 2785 /* 2786 * execute cross domain request, JSON response 2787 * 2788 * @param {type} params 2789 * @param {type} callback 2790 * @returns {@exp;$@call;post} 2791 */ 2792 self.xhrPost = function (params, callback) { 2793 var data = params; 2794 if (params.format === undefined) { 2795 params.format = 'json'; 2796 } 2797 data.action = 'cross_domain_request'; 2798 2799 return $.ajax({ 2800 type: "POST", 2801 url: ajaxproxy, 2802 data: data, 2803 success: function (response) { 2804 if (typeof callback === 'function') { 2805 callback(response); 2806 } 2807 }, 2808 dataType: params.format, 2809 error: function (xhr, textStatus, errorThrown) { 2810 alert("An error occurde. This might be a conflict with another plugin. Error message: " + textStatus); 2811 } 2812 }); 2813 }; 2814 /* 2815 * show loading spinner 2816 */ 2817 self.showLoading = function () { 2818 if ($('.fontLoading').length) { 2819 //self.$apr.find('fieldset').hide(); 2820 //self.$el.find('> div').hide(); 2821 $('.fontLoading').show(); 2822 $('.fontLoading').show(); 2823 } else { 2824 $('body').append('<div class="fontLoading"></div>'); 2825 } 2826 }; 2827 /* 2828 * hide loading spinner 2829 */ 2830 self.hideLoading = function () { 2831 $('.fontLoading').hide(); 2832 $('.fontLoading').hide(); 2833 }; 2834 /* 2835 * detect if we're on post editing page or on any other page 2836 */ 2837 self.detectMode = function () { 2838 var iframe = $('#content_ifr'); 2839 if (iframe.length) { 2840 self.mode = 'postPage'; 2841 self.postIframe = iframe.contents(); 2842 //self.tinyMCE = $(self.postIframe).find('#tinymce'); 2843 } else { 2844 self.mode = 'global'; 2845 } 2846 // detect CSS text-shadow support in JavaScript 2847 if (document.createElement("detect").style.textShadow === "") { 2848 self.shadowSupport = true; 2849 } else { 2850 self.shadowSupport = false; 2851 } 2852 }; 2853 // finally INIT 2854 self.init(); 2855 }; 2856 /* 2857 * set default options 2858 */ 2859 $.fontPlugin.defaultOptions = { 2860 FFW_baseUrl: 'http://fontsforweb.com' 2861 }; 2862 /* 2863 * make jquery plugin 2864 */ 2865 $.fn.fontPlugin = function (options) { 2866 return this.each(function () { 2867 var fontPlugin = new $.fontPlugin(this, options); 2868 }); 2869 }; 2870 /* 2871 * HANDLE PLUGIN 2872 * 2873 * options 2874 * startX -vstarting position 2875 * startY -vstarting position 2876 * name - handle name 2877 * label - visible label 2878 * 2879 */ 2880 var XYSlider = function (el, options) { 2881 var self = this; 2882 self.$el = $(el); 2883 self.$el.data('XYSlider', self); 2884 // immediate init funciton 2885 self.init = function () { 2886 // get handle element by name 2887 var handleHolder = self.$el.data(options.settingName), 2888 handle = (handleHolder && handleHolder[0]) ? handleHolder.find('.XYSlider')
2888: false; 2889 // if doesn't exist create the handle 2890 if (!handleHolder || !handleHolder[0]) { 2891 handleHolder = $('<div class="XYSliderHolder"></div>'); 2892 handle = $('<div class="XYSlider">' + options.label + '</div>'); 2893 handleHolder.append(handle); 2894 self.$el.append(handleHolder); 2895 } 2896 self.$el.data(options.settingName, handleHolder); 2897 // save in object 2898 self.$handleHolder = handleHolder; 2899 self.$handle = handle; 2900 // make handle draggable 2901 handle.each(function () { 2902 // show handle 2903 $(this).parent().show(); 2904 // make draggable 2905 $(this).draggable({ 2906 drag: function (event, ui) { 2907 var top = ui.position.top, 2908 left = ui.position.left, 2909 // revert top: more is higher 2910 y = -top, 2911 x = options.invertX ? -left : left; 2912 self.commitDrag(x, y, true); 2913 } 2914 }); 2915 }); 2916 }; 2917 /* 2918 * Change position of draggable 2919 * 2920 * x - x position 2921 * y - y position 2922 */ 2923 self.setPosition = function (x, y) { 2924 var handle = self.$handle; 2925 2926 if (x !== false) { 2927 self.x = x; 2928 } else if (self.x === undefined) { 2929 x = 0; 2930 self.x = 0; 2931 } else { 2932 x = self.x; 2933 } 2934 if (y !== false) { 2935 y = y; 2936 self.y = y; 2937 } else if (self.y === undefined) { 2938 y = 0; 2939 self.y = 0; 2940 } else { 2941 y = self.y; 2942 } 2943 if (x === false && y === false) { 2944 return; 2945 } 2946 // move x and y - revert top: more is higher 2947 handle.css({ 2948 'top': -y + 'px', 2949 'left': (options.invertX ? -x : x) + 'px' 2950 }); 2951 // commit drag 2952 self.commitDrag(x, y, true); 2953 }; 2954 /* 2955 * Execute callbacks 2956 */ 2957 self.commitDrag = function (x, y, stop) { 2958 var rad = Math.atan2(x, y), 2959 deg = rad * (180 / Math.PI), 2960 distance = 0; 2961 if (stop === undefined) { 2962 stop = false; 2963 } 2964 //get angle 2965 if (deg < 0) { 2966 deg = 360 + deg; 2967 } 2968 // round angle to full degrees 2969 deg = Math.round(deg); 2970 // calculate distance 2971 distance = Math.sqrt(x * x + y * y); 2972 // set current values 2973 self.setCurrentValues(x, y, deg, distance); 2974 // call actions 2975 options.actions.call(this, x, y, deg, distance); 2976 }; 2977 self.setCurrentValues = function (x, y, deg, distance) { 2978 self.x = x; 2979 self.y = y; 2980 self.deg = deg; 2981 self.distance = distance; 2982 return self; 2983 }; 2984 self.getCurrentValues = function () { 2985 return { 2986 'x': self.x, 2987 'y': self.y, 2988 'deg': self.deg, 2989 'distance': self.distance 2990 }; 2991 }; 2992 self.init(); 2993 }; 2994 // use prototype 2995 $.fn.XYSlider = function (options) { 2996 return this.each(function () { 2997 //new XYSlider(this, options); 2998 //var pluginName = 'XYSlider'; 2999 new XYSlider(this, options); 3000 }); 3001 }; 3002}(fQuery));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.