TweetFollow Us on Twitter

AppleScripting EGO

Volume Number: 13 (1997)
Issue Number: 5
Column Tag: develop

According to Script: An External Editing Apple Event Protocol

by Cal Simone

In recent years, Macintosh developers have begun to move away from large, monolithic programs in favor of a more modular approach to software, producing leaner, more efficient applications that don't try to do everything. An effective way to accomplish this is through external editing, in which one application uses Apple events to call upon another application for editing services. External editing allows your application to take advantage of editors implemented as Apple event-based server applications, which I discussed in develop Issue 29 that can be found at http://17.126.23.20/dev/toc.shtml.

In this column, I'll be exploring the advantages of implementing external editing and the basics of making it work, and I'll also present a good starting point for a general external editing implementation. At this time, there is no generally applicable external editing suite that's part of the Apple Event Registry. However, there is a suite in fairly wide use that's designed specifically for external editing of graphic objects in word processing documents (discussed later), and the more general external editing suite presented here is largely derived from it.

Types of Apple Event Usage

First let's look at the types of Apple event usage to see how external editing fits in. In general, there are three ways Apple events can be used:

• Direct program-to-program communication between two applications - One or both applications have intimate knowledge of the other's Apple event protocol. Either or both of the applications can be the client or the server. This usage has largely faded from practice.

• Service modules - A client application calls upon the services of another application as though that application were embedded in the client. An example is the relationship between a word processor and a spell checker. External editing falls in this category.

• Scripting - Lots of scriptable applications are hanging out, saying "I'm available" and "This is what I do." The scripting language is the client, and it doesn't have to determine which parts of the Apple event protocol of the scriptable applications are necessary to control them; that's the scripter's responsibility.

Advantages of External Editing

There are several advantages to implementing external editing:

• Developers can effectively extend the capabilities of their applications by leveraging off of applications from other vendors, so it's not necessary to implement an editor for each data type supported by your application.

• Since each developer has a smaller code base to manage, applications will have fewer bugs.

• Users can pick and choose the combination of tools they like from different vendors, benefiting from the advantages that a stand-alone editor designed for specialized usage can offer, while retaining access to all the features of the client application.

• Users can use one environment for editing the same kind of data, regardless of which applications they work in, enjoying a consistent experience.

If the above sound familiar, that's because these same advantages are central to OpenDoc's philosophy. In the non-OpenDoc world, you can achieve much the same effect by implementing external editing.

Note that in this discussion, client means the application requesting the edit (not the actual user), and editor means the server application. Any application implementing the Apple event object model and the Core suite can easily take advantage of external editing as a client, since most of the work is done by the server.

An Eventful History

The work done in the Word Services Apple event suite paved the way for a consistent services protocol. However, the details of that suite are somewhat specific to spell-checking and similar service modules, where the client and server interact more intimately. A modified version of the EGO (Edit Graphic Object) protocol is better suited to external editing's needs. The main difference between EGO and the external editing protocol that I describe here is that external editing relies less on custom Apple events and parameters than on existing events defined in the Apple Event Registry, in particular the Core suite, and can therefore be quicker to implement.

In EGO, the user double-clicks on an object in a client application, a server application appears with the object in an editing window, the user edits the object and dismisses the window, and the edited version appears in place in the client's window. EGO was originally developed so that mathematical equations in word processing documents could be edited in a full-featured equation editor. However, it was designed for more general use as an external editing mechanism for graphics embedded in text documents. The first shipping implementation in 1991 was used to link Expressionist to Microsoft Word. EGO and extended versions of EGO have been implemented in word processors, such as WordPerfect, Nisus, and FullWrite, as well as other types of applications, such as Theorist, SigmaPlot, and Chem3D. (See http://www.well.com/~bonadio/aba/ego.html for more details on EGO.)

Although not a part of the Apple Event Registry, the external editing protocol that I describe here, and a version that included extensions applicable to script editing, are based on EGO concepts and were developed in 1993. These ideas were shaped in discussions between Allan Bonadio, founder of Prescience, Michael Rubenstein of CambridgeSoft, Lee Buck of Software Designs Unlimited, and myself, and were reviewed by others. In 1995, a portion of the scripting version was implemented in FaceSpan and Scripter to allow editing and debugging of scripts in a stand-alone script editor. Currently shipping versions of third-party stand-alone script editors include some form of the protocol, with extensions or variations.

Please note that to make the external editing protocol useful for as wide a range of data, clients, and editors as possible, I haven't included the parts of EGO or its variations that are specific to editing particular data types. I'm going to concentrate here on general-case scenarios and the Apple event protocols - the operations that can form the basis for external editing. This is not a complete treatment of external editing by any means; in particular, I'll mostly steer away from user interface issues and discussions of error handling, both of which are important issues that need to be addressed in any complete external editing suite. The goal of this column is to serve as a catalyst to speed the creation and adoption of such a suite.

To be Modal or Non-Modal?

The external editing protocol was designed to allow both modal and non-modal editing. In modal editing, the client application requests the services of the editor and waits for the user to finish editing. The editor returns the edited item to the client, and the client resumes operation. This modal editing situation prevents the user from working in the client application during the editing session. I highly discourage anyone from going this (user-unfriendly) route. The freedom, ease, and elegance of non-modal editing far outweigh any superficial advantages of modal editing. Modal editing is not recommended and won't be discussed further here.

In the less rigid world of non-modal editing, the client application requests the services of the editor and allows the user to edit asynchronously. During the editing session, the client uses whatever version of the object it has, either the original or an updated version. When the editing is done, the editor replaces the object. As optional parts of the protocol, the client can request the return of the currently edited version at any time or cause the editing session to be abandoned.

What You Need to do

If you're already supporting the object model and the Core suite, all you need to do is write the code to send (for clients) or handle (for editors) one new Apple event, and optionally handle (for clients) or send (for editors) another new Apple event. If you don't support the object model, this is a good excuse to get started; you just have to write the additional code to support three Core events that are used in the external editing protocol. Now let's take a look at how all this can be accomplished.

Initiating the edit

The user requests an edit, through some action in the user interface of the client application. The mechanism by which a user initiates an editing session is not specified as part of the protocol. You can decide what's appropriate for your application - possibilities include double-clicking (perhaps with a modifier key held down) on an object in one of the client's windows, clicking a tool in a palette, or choosing a menu item or button to act on the current selection.

The client application requests an editing session by sending an Edit Apple event to the editor application. The Edit event, summarized in Table 1, is similar to the Edit Graphic event in the Miscellaneous Standards of the Apple Event Registry.

The direct parameter of the Edit event is an object specifier, which is a reference to the item to be edited. I'll call this the client's original item reference. You can use any form of object specifier that suits you, although it's important to create an object specifier that will always refer to that specific object regardless of the state of the application - formUniqueID fits the bill. Note that both formAbsolutePosition and formName should be avoided as object specifiers in this case, because references by index can change as items are rearranged while the edit is occurring, and names may not be unique and can be changed at any time.

It's also a good idea to include a name parameter (using the keyAEName keyword), which is a text string that the editor can use as the title for the editing window. Usually this is the name of the item that's being edited, although you can make it something else, if appropriate.

The client can include an optional return type parameter (using the keyAERequestedType keyword) to specify the type for the updated data when it's sent back to the client after editing. In addition, the client might want an editing window to be positioned at the same place on the screen as the original item appears in the client's window. To do this, the client can include an optional parameter (using the keyAEPosition or keyAEBounds keyword) indicating the position or bounds that the editor can use to determine the location for the editing window. The value of this parameter could be the client's global screen coordinates of the visible object.

Finally, it's a good idea to include a session ID parameter (using the keyAEUnique keyword, with the ID 'Uniq'). The session ID parameter value is a long integer of the client's choosing, such as TickCount, that uniquely identifies the editing session.

If the attempt to send the Edit event results in the error procNotFound, the editor isn't running. If this happens, the client should launch the editor and send the Apple event again.

The editor receives the client's request for an editing session and handles the Edit event, causing the following actions to occur:

1. The editor extracts the original item reference from the direct parameter (and the session ID parameter value, if the client included it) and keeps this value with the data for the editing session.

2. In the direct parameter of the reply Apple event, the editor places a new object specifier, which is a reference to the editing session. I'll call this the editing session reference. The editor then returns from handling the Edit event.

3. The editor requests the item to be edited from the client by sending the client a Get Data Apple event, passing the client's original item reference as the direct parameter.

4. The client responds to the Get Data event by resolving the original item reference in the direct parameter (which the client itself originally generated), inserting the data for the item to be edited in the direct parameter of the reply, and returning from handling the Get Data event.

5. The editor extracts the item's data from the reply to the Get Data event, opens an editing window, and places this data in the window.

6. The editor is brought to the foreground, ready to edit the data. If the client launched the editor and requested that it be brought to the foreground, this will happen automatically; otherwise the editor can bring itself to the foreground. (How to do this is discussed in my last column, and as I said there, this is just about the only situation where it's reasonable for a server application to force itself into the foreground without asking the user to switch applications.)

Finally, both applications return to their main event loops, with the editor now in front. The appropriate suspend/resume and activate events are delivered by the system and handled by both applications as expected.

Early versions of the Apple Event Manager imposed a 64K limit on the size of data in an Apple event, including the attributes and any parameter data. Your application should be prepared to deal properly with this. The limit is not an issue if AppleScript 1.1 is running, and the limit has been completely removed in MacOS 7.6.

Performing the edit

The user performs the desired edits in the editor application. In this non-modal situation, the user can switch to other programs, including the client application, while editing. The user can even initiate an editing session for a different item from the same client - the original item references and the editing session references keep things straight.

Generally speaking, while the user is editing an item in the editor, the client should not allow any action that would cause that item to be modified. If the user again requests an edit of the same item, the client should send an Edit event that is identical to the original edit request, with the same object specifier and session ID parameter. Under normal circumstances the editor should not initiate another editing session for that item. The correct behavior is for the editor to activate the editing window corresponding to the original item.

Terminating the edit (from the editor)

The user finishes editing by closing the editing window in the editor application. If there is changed data, then before the window is actually dismissed the editor should display an alert, asking the user to confirm that the changes should be sent back to the client. If the user so confirms, the editor creates and sends a Set Data Apple event to the client application, passing the client's original item reference in the direct parameter, and the updated item data in the data parameter (using the keyAEData keyword). If the client included a session ID parameter with the original edit request, this parameter is also included in the Set Data event.

The client application responds by resolving the original item reference and extracting the updated data from the data parameter. The client can replace the original item with the updated data or otherwise use the data in whatever manner it sees fit, such as updating a database or broadcasting the change to other applications. The presence of the session ID parameter tells the client that this Set Data event is associated with the editing session, as opposed to any other Set Data event that might change the data for the original item. After the client returns from handling the Set Data event, the editor may safely dismiss the editing window.

If appropriate, the client could now be brought to the foreground. At this point both applications have again returned to their respective main event loops, and the user may continue working, using the new version of the edited item. The user has had a smooth editing experience and is happy.

Extend Your Options

In addition to the basic process described above, there are several options that may be implemented by either the client or the editor. Implementing these options requires only that you send no more than three additional Core Apple events (two of which are Apple events you must handle anyway) and handle one new Apple event.

Working with interim versions of the edit. During the editing session, the user may want to try out versions of the edited item without terminating the editing session. Here's one way to accommodate this:

1. The user requests an interim version be sent to the client application (by choosing a Send Back command like that in Scripter, for example, or perhaps by choosing Save).

2. The editor creates a Set Data Apple event containing the current version of the edited item's data, the same as it does when terminating the edit, and sends the Apple event to the client application.

3. The client application extracts the updated data from the Apple event.

4. The user tries out the updated version of the item.

In general, the client application will know when an updated version of the item is received via a Set Data event by the presence of the session ID parameter, but it may not know when the editing session is completely finished. If the client does need to know when the edit is finished, in order to stop keeping track of whether the item has an outstanding editing session, the client can request that the editor notify the client when the editing session is finally done. The editing completion notification request is made when the client first initiates the external editing process (more on this below).

Calling the edit back (terminating the edit from the client)

If the client application allows it, a user may (while in the middle of editing) delete or copy the original item in the client application, close the window containing the original item, or quit the client application. In any of these situations, the client application may need to obtain the currently edited version of the item and/or terminate the editing session. Essentially, the data in any outstanding editing session is an extension of the client's application or document data at large and must be called back for any reason that requires the current value of the item's data.

Note that the act of closing the server's window is not required, but it is highly recommended. Leaving the editing window open creates a situation where later closing the window and confirming the changes could result in problems. The editor might attempt to send a Set Data Apple event to an application that's no longer running, or with an object reference that's no longer valid. Even worse, the object reference might be valid, but now refers to a different object (depending on the nature of the object specifier).

To call an edit back and terminate the edit:

1. The client terminates the editor's editing session by sending the editor a Close Apple event, with the editing session's reference in the direct parameter and an optional kAESaveOptions parameter. The value of kAESaveOptions determines whether the updated data is called back to the client; the default value is kAEAsk.

2. The editor receives the Close event, extracts and resolves the editing session reference, and extracts the keyAESaveOptions parameter, if present. If the value of keyAESaveOptions is kAENo (sent when the client isn't interested in the updated data), the editor returns noErr as the result of its event handler, closes the window, discards the data, and skips the remaining steps. If the value is kAEYes, the editor proceeds to step 4.

3. If the editor finds a keyAESaveOptions parameter with a value of kAEAsk, it displays an alert confirming that changes should be sent back to the client. If the user clicks Cancel, the editor returns userCanceledErr as the result of handling the Close event, the client abandons the current operation, and the remaining steps are skipped. If the user clicks Don't Send, the editor discards the edited data, closes the editing window, and returns noErr as the result of handling the Close event, and the remaining steps are skipped.

4. The editor creates a Set Data event containing the current version of the item's data and sends this event to the client. The client must implement idle and filter procs to handle the incoming Set Data event while the Close event is outstanding, otherwise this will result in an Apple event deadlock.

5. The client checks the result of sending the Close event. If the result is userCanceledErr, the client cannot quit or close the window containing the original item.

6. The editor discards the edited data and closes the window.

Reverting to a previous version (by the editor)

While working in the editor, the user may want to revert to a previous version of the edited item. If the user chooses Revert from the editor's File menu, the editor should display a standard "Revert to last version?" alert, then replace the altered version with the original version from the client. To revert to the client's version:

1. The editor requests the previous version of the edited item by sending a Get Data Apple event to the client, with the original item reference in the direct parameter.

2. The client replies with its current version of the item's data in the direct parameter of the reply to the Get Data event.

3. The editor extracts the earlier version from the direct parameter of the reply and displays it in the editing window, in place of the edited version. The user may now continue with the editing session.

Checking the status of an edit (by the client)

If the client wants to know whether the editing session is still in progress, it can send a Does Object Exist Apple event to the editor, with the editing session reference in the direct parameter. If the reply contains a Boolean value of false or if you get a procNotFound error, it's no longer a good idea for the client to send a Close or Get Data event for the editing session; the client can conclude that the editing session has been abandoned or the editor has crashed. The client can deal with the possibility of not receiving a completed edit by notifying the user with an alert explaining that the editing session may have been abandoned.

Checking the status of an edit (by the editor)

Sometimes it can be helpful for the editor to know whether the client is able to receive the results of a completed edit. The editor can check just before it sends back the updated data for the item by sending a Does Object Exist Apple event to the client application, with the client's original item reference in the direct parameter. If the editor doesn't successfully receive a reply (or receives a reply with a Boolean value of false) to the Does Object Exist event, the editor can assume that conditions in the client application for receiving updated item data are unfavorable and that it should not attempt to send back updated versions of the item. The editor can notify the user by putting up an alert, asking if the edited version should be saved to a file or abandoned.

To determine whether an editing session is still valid, the editor can check periodically for the existence of the client's original item on which the edit is based. One way to do this is with a heartbeat, which is requested by the client when the edit is initiated by including the optional heartbeat parameter (using a keyAESendHeartbeat keyword, with the ID ‘kChk') in the Edit Apple event.

Notification of editing completion

If an original item still has outstanding edits, it may not be safe to close the window, delete the item, or quit the client application. A client application that's keeping track of outstanding edits can optionally request that the editor notify it when the editing session is finished.

The client requests notification of editing completion when the edit is initiated, by including the optional notify parameter (using a keyAENotifyWhenDone keyword, with the ID ‘kNot') in the Edit Apple event. Then, when the user closes the window or quits the editor, and after the final Set Data event, if any, has been sent to the client, the editor will send an Editing Is Done Apple event (necessary even if no changes were made in the editing session). The Editing Is Done event is summarized in Table 2. The client responds to this event by noting internally that the editing session is completed.

Sending the original data to be edited in the edit request

There are situations where there's no object to be edited in the client application, such as when the client wants to request editing for data that's in a file on disk. In situations where the client isn't directly concerned with the editing session, it can send an Open Apple event to the editor with a file reference or alias to the file to be edited in the direct parameter. This is proper when the data to be edited isn't embedded in a client's document or application data, and the client isn't responsible for storing the updated data; the editor takes care of this.

On the other hand, when parts of a document are stored in separate files, as with a page layout application, it's better that the client use the normal methods outlined above, creating Edit Apple events and object specifiers. While it is possible to send the actual data for the item to be edited in the direct parameter of the Edit Apple event, I generally don't recommend this approach. The solution is to support the object model; in this day and age, this is simply the best way.

Be a Pioneer

Obviously, every aspect of the client/editor relationship hasn't been explored here. As you transform your application into a client or editor, you'll run into user interface issues that need to be worked out, and you'll need to implement appropriate and robust error handling. But right now, with just a few bits of code, you can begin to implement the external editing protocol as either a client or an editor and try it out. If you don't yet support the object model, this is your chance to get with the program.

Talk to other developers whose applications you want to work with, and get the discussion going. A good place to start is the applescript-implementors mailing list (to join, see http://www.solutions.apple.com/ListAdmin/). With a little luck, and a little work, we'll soon have a complete specification that works for most everyone. Users will thank us for it, as they'll be able to experience the richness of using our applications in a variety of new situations.

Thanks to Andy Bachorski, Allan Bonadio, and Jon Pugh for reviewing this column. Allan generously donated the use of the EGO concepts, and Michael Rubenstein insistently convinced the author to look at EGO. Lee Buck worked with the author to simplify the events.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

NetNewsWire 5.0.4 - RSS and Atom news re...
NetNewsWire is the best way to keep up with the sites and authors you read most regularly. Let NetNewsWire pull down the latest articles, and read them in a distraction-free and Mac-like way. Native... Read more
EarthDesk 7.4.5 - $24.99
EarthDesk replaces your static desktop picture with a rendered image of Earth showing correct sun, moon, and city illumination. With an Internet connection, EarthDesk displays near-real-time global... Read more
BetterTouchTool 3.401 - Customize multi-...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom)... Read more
Vienna 3.5.6 :e12c952d: - RSS and Atom n...
Vienna is a freeware and Open-Source RSS/Atom newsreader with article storage and management via a SQLite database, written in Objective-C and Cocoa, for the OS X operating system. It provides... Read more
WhatsApp 2.2031.5 - Desktop client for W...
WhatsApp is the desktop client for WhatsApp Messenger, a cross-platform mobile messaging app which allows you to exchange messages without having to pay for SMS. WhatsApp Messenger is available for... Read more
Day One 4.16 - Maintain a daily journal.
Day One is an easy, great-looking way to use a journal / diary / text-logging application. Day One is well designed and extremely focused to encourage you to write more through quick Menu Bar entry,... Read more
VMware Fusion 11.5.6 - Run Windows apps...
VMware Fusion and Fusion Pro - virtualization software for running Windows, Linux, and other systems on a Mac without rebooting. The latest version includes full support for Windows 10, macOS Mojave... Read more
Alfred 4.1 - Quick launcher for apps and...
Alfred is an award-winning productivity application for OS X. Alfred saves you time when you search for files online or on your Mac. Be more productive with hotkeys, keywords, and file actions at... Read more
Dashlane 6.2032.0 - Password manager and...
Dashlane is an award-winning service that revolutionizes the online experience by replacing the drudgery of everyday transactional processes with convenient, automated simplicity - in other words,... Read more
Skype 8.63.0.76 - Voice-over-internet ph...
Skype is a telecommunications app that provides HD video calls, instant messaging, calling to any phone number or landline, and Skype for Business for productive cooperation on the projects. This... Read more

Latest Forum Discussions

See All

Motorball is a car football game from No...
A few years back Noodlecake Studios announced that they would be dipping in the multiplayer gaming realm with two different games. The first of those, Golf Blitz, released a while back and has proven to be very popular. Now, the second has arrived... | Read more »
SINoALICE's latest update introduce...
SINoALICE's latest update has now arrived, adding several fan-favourite characters from popular RPG series NieR. Young Nier, Kaine, and Young Emil are available in-game as part of a limited-time crossover event set to run until August 20th. [Read... | Read more »
Rocat Jumpurr is an intense roguelite pl...
Rocat Jumpurr is a roguelite platformer from developer Mousetrap Games. You might already be familiar with it if you follow the Big Indie Pitch, where it won first place during this year's Pocket Gamer Connects London competition. Following its... | Read more »
PUBG Mobile's Play As One campaign...
Back in mid-July, we reported that PUGB Mobile had teamed up with Direct Relief to help raise money for the charity's COVID-19 response project. It focused on an in-game running challenge for players, which lead to the PUBG Mobile donating $2... | Read more »
Marvel Contest of Champions' latest...
Marvel Contest of Champions' latest motion comic has arrived, and it shows off new fighters Air-Walker and Dragon Man. Both characters are set to arrive in-game this month. [Read more] | Read more »
Clash Royale: The Road to Legendary Aren...
Supercell recently celebrated its 10th anniversary and their best title, Clash Royale, is as good as it's ever been. Even for lapsed players, returning to the game is as easy as can be. If you want to join us in picking the game back up, we've put... | Read more »
Global Spy is an intriguing 2D spy sim f...
Developer Yuyosoft Innovations' Global Spy launched last month for iOS and Android, though if you missed it at the time, we're here to tell you why it's well worth a go. This one's all about international espionage, tracking down elusive spies,... | Read more »
Distract Yourself With These Great Mobil...
There’s a lot going on right now, and I don’t really feel like trying to write some kind of pithy intro for it. All I’ll say is lots of people have been coming together and helping each other in small ways, and I’m choosing to focus on that as I... | Read more »
Hyena Squad is sci-fi turn-based strateg...
Wave Light Games has just revealed its latest release, Hyena Squad, a turn-based RPG set in a space station infested by gross aliens and the living dead. The announcement was first reported on by Touch Arcade. [Read more] | Read more »
Idle Guardians: Never Die is a pixel art...
SuperPlanet has been fairly prolific with game releases so far this year with both Evil Hunter Tycoon and Lucid Adventure releasing earlier this year. Now, they've released another idle RPG called Idle Guardians: Never Die, which you can download... | Read more »

Price Scanner via MacPrices.net

Save hundreds of dollars on a custom-configur...
Save up to $920 on a custom-configured 16″ MacBook Pro with these Certified Refurbished models that Apple has restocked today. Each MacBook Pro features a new outer case, free shipping, and includes... Read more
New 2020 12.9″ iPad Pros on sale for up to $8...
Apple reseller Expercom has new 2020 Apple 12.9″ iPad Pros on sale today for $60-$85 off MSRP, with prices starting at $939. These are the same iPad Pros sold by Apple in their retail and online... Read more
Woot offers numerous 2018-2020 MacBook Pros a...
Amazon-owned Woot has many open-box return MacBook Airs and MacBook Pros available today at prices starting at $879. Shipping is free for Prime members. Here’s what they have as of this post, and... Read more
Apple restocks refurbished 2020 13″ MacBook A...
Apple has restocked Certified Refurbished 2020 13″ MacBook Airs starting at only $849 and up to $200 off the cost of new Airs. Each MacBook features a new outer case, comes with a standard Apple one-... Read more
Apple restocks clearance 2019 13″ 2.4GHz MacB...
Apple has restocked Certified Refurbished 2019 13″ 2.4GHz 4-Core Touch Bar MacBook Pros starting at $1359 and up to $560 off original MSRP. Apple’s one-year warranty is included, shipping is free,... Read more
Apple restocks refurbished iPhone XR models s...
Apple has restocked Certified Refurbished, unlocked, iPhone XR models in the refurbished section of their online store starting at $539. Each iPhone comes with Apple’s standard one-year warranty,... Read more
Price drops! $100-$200 off clearance 27″ 5K i...
B&H Photo has dropped prices on clearance, previous-generation 27″ 5K iMacs by up to $200 off Apple’s original MSRP: – 27″ 3.0GHz 6-Core 5K iMac: $1699 $100 off original MSRP – 27″ 3.1GHz 6-Core... Read more
Woot offers Apple Watch and iPhone models fro...
Amazon-owned Woot has refurbished Apple Watch and iPhone models available from $99-$749 through August 6th. According to Woot, the items may show some wear, but they have all been fully tested and... Read more
Apple’s Phil Schiller Steps Down As SVP OF Wo...
NEWS: 08.05.20 – Former Apple senior Vice President of worldwide marketing, Phil Schiller, is stepping down from his long time role at the company in order to focus on spending more time with family... Read more
Expercom offers $320 discount on the 6-core 1...
Apple reseller Expercom has the Silver 16″ 6-core MacBook Pro on sale for a limited time for $2079 shipped. Their price is $320 off Apple’s MSRP for this model, and it’s the cheapest price currently... Read more

Jobs Board

Blue *Apple* Cafe Student Worker - Fall - P...
…to enhance your work experience. Student positions are available at the Blue Apple Cafe. Employee meal discount during working hours is provided. Duties include food Read more
Cub Foods - *Apple* Valley - Now Hiring Par...
Cub Foods - Apple Valley - Now Hiring Part Time! United States of America, Minnesota, Apple Valley New Retail Post Date 4 days ago Requisition # 122305 Sign Up Read more
Cub Foods - *Apple* Valley - Now Hiring Par...
Cub Foods - Apple Valley - Now Hiring Part Time! United States of America, Minnesota, Apple Valley New Retail Post Date 3 days ago Requisition # 122305 Sign Up Read more
Executive Team Leader GM Sales (Assistant Man...
…(Assistant Manager General Merchandise and Operations) - Apple Valley, CaliforniaApply NowJob ID:R0000082364job family:Store Managementschedule:Full Read more
Cub Foods - *Apple* Valley - Now Hiring Par...
Cub Foods - Apple Valley - Now Hiring Part Time! United States of America, Minnesota, Apple Valley New Retail Post Date 2 days ago Requisition # 122305 Sign Up Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.